diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,37 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+## 0.5.0
+### Added
+- Support for Bitcoin Cash network block sychronization.
+- Support for Bitcoin Cash signatures.
+- Initial work on SegWit support.
+- New version of `secp256k1` bindings.
+- Block header validation.
+- Support for RegTest networks on Bitcoin and Bitcoin Cash.
+- Support for Bitcoin Cash Testnet3 Network.
+- Support for new Haskoin Wallet.
+- Minikey decoding for Casascius coins.
+- New tests for various networks and new features.
+- Added `CHANGELOG.md` file.
+- Support for SegWit addresses.
+- Support for CashAddr addresses.
+
+### Changed
+- Use of hpack `package.yaml` file to auto-generate Cabal file.
+- Removal of dependency version limits, relying on `stack.yaml` instead.
+- Tests moved to `hspec`.
+- New documentation.
+- Updated `.gitignore`.
+- Renamed network constants to use same style for BTC and BCH.
+- Network constants must be passed explicitly.
+- Target LTS Haskell 12.9.
+
+### Removed
+- Removed `.stylish-haskell.yaml` files.
+- Removed old `haskoin-node` and `haskoin-wallet` packages from main repository.
+- Removed support for non-strict signatures and related tests.
+- Removed script evaluator and related tests.
diff --git a/Network/Haskoin/Block.hs b/Network/Haskoin/Block.hs
deleted file mode 100644
--- a/Network/Haskoin/Block.hs
+++ /dev/null
@@ -1,47 +0,0 @@
-{-|
-  This package provides block and block-related types.
--}
-module Network.Haskoin.Block
-(
-  -- * Blocks
-  Block(..)
-, BlockLocator
-, GetBlocks(..)
-
-  -- * Block Headers
-, BlockHeader
-, createBlockHeader
-, blockVersion
-, prevBlock
-, merkleRoot
-, blockTimestamp
-, blockBits
-, bhNonce
-, headerHash
-, GetHeaders(..)
-, Headers(..)
-, BlockHeaderCount
-, BlockHash(..)
-, blockHashToHex
-, hexToBlockHash
-
-  -- * Merkle Blocks
-, MerkleBlock(..)
-, MerkleRoot
-, FlagBits
-, PartialMerkleTree
-, calcTreeHeight
-, calcTreeWidth
-, buildMerkleRoot
-, calcHash
-, buildPartialMerkle
-, extractMatches
-
-  -- * Difficulty Target
-, decodeCompact
-, encodeCompact
-) where
-
-import Network.Haskoin.Block.Types
-import Network.Haskoin.Block.Merkle
-
diff --git a/Network/Haskoin/Block/Merkle.hs b/Network/Haskoin/Block/Merkle.hs
deleted file mode 100644
--- a/Network/Haskoin/Block/Merkle.hs
+++ /dev/null
@@ -1,206 +0,0 @@
-module Network.Haskoin.Block.Merkle
-( MerkleBlock(..)
-, MerkleRoot
-, FlagBits
-, PartialMerkleTree
-, calcTreeHeight
-, calcTreeWidth
-, buildMerkleRoot
-, calcHash
-, buildPartialMerkle
-, extractMatches
-) where
-
-import           Control.DeepSeq                   (NFData, rnf)
-import           Control.Monad                     (forM_, replicateM)
-import           Data.Bits
-import qualified Data.ByteString                   as BS
-import           Data.Maybe
-import           Data.Serialize                    (Serialize, encode, get, put)
-import           Data.Serialize.Get                (getWord32le, getWord8)
-import           Data.Serialize.Put                (putWord32le, putWord8)
-import           Data.Word                         (Word32, Word8)
-import           Network.Haskoin.Block.Types
-import           Network.Haskoin.Constants
-import           Network.Haskoin.Crypto.Hash
-import           Network.Haskoin.Node.Types
-import           Network.Haskoin.Transaction.Types
-
-type MerkleRoot        = Hash256
-type FlagBits          = [Bool]
-type PartialMerkleTree = [Hash256]
-
-data MerkleBlock =
-    MerkleBlock {
-                -- | Header information for this merkle block.
-                  merkleHeader :: !BlockHeader
-                -- | Number of transactions in the block (including
-                -- unmatched transactions).
-                , merkleTotalTxns :: !Word32
-                -- | Hashes in depth-first order. They are used to rebuild a
-                -- partial merkle tree.
-                , mHashes :: ![Hash256]
-                -- | Flag bits, packed per 8 in a byte. Least significant bit
-                -- first. Flag bits are used to rebuild a partial merkle
-                -- tree.
-                , mFlags :: ![Bool]
-                } deriving (Eq, Show, Read)
-
-instance NFData MerkleBlock where
-    rnf (MerkleBlock m t h f) = rnf m `seq` rnf t `seq` rnf h `seq` rnf f
-
-instance Serialize MerkleBlock where
-
-    get = do
-        header <- get
-        ntx    <- getWord32le
-        (VarInt matchLen) <- get
-        hashes <- replicateM (fromIntegral matchLen) get
-        (VarInt flagLen)  <- get
-        ws <- replicateM (fromIntegral flagLen) getWord8
-        return $ MerkleBlock header ntx hashes (decodeMerkleFlags ws)
-
-    put (MerkleBlock h ntx hashes flags) = do
-        put h
-        putWord32le ntx
-        put $ VarInt $ fromIntegral $ length hashes
-        forM_ hashes put
-        let ws = encodeMerkleFlags flags
-        put $ VarInt $ fromIntegral $ length ws
-        forM_ ws putWord8
-
-decodeMerkleFlags :: [Word8] -> [Bool]
-decodeMerkleFlags ws =
-    [ b | p <- [0..(length ws)*8-1]
-    , b <- [testBit (ws !! (p `div` 8)) (p `mod` 8)]
-    ]
-
-encodeMerkleFlags :: [Bool] -> [Word8]
-encodeMerkleFlags bs = map boolsToWord8 $ splitIn 8 bs
-
--- | Computes the height of a merkle tree.
-calcTreeHeight :: Int -- ^ Number of transactions (leaf nodes).
-               -> Int -- ^ Height of the merkle tree.
-calcTreeHeight ntx | ntx < 2 = 0
-                   | even ntx  = 1 + calcTreeHeight (ntx `div` 2)
-                   | otherwise = calcTreeHeight $ ntx + 1
-
--- | Computes the width of a merkle tree at a specific height. The transactions
--- are at height 0.
-calcTreeWidth :: Int -- ^ Number of transactions (leaf nodes).
-              -> Int -- ^ Height at which we want to compute the width.
-              -> Int -- ^ Width of the merkle tree.
-calcTreeWidth ntx h = (ntx + (1 `shiftL` h) - 1) `shiftR` h
-
--- | Computes the root of a merkle tree from a list of leaf node hashes.
-buildMerkleRoot :: [TxHash]   -- ^ List of transaction hashes (leaf nodes).
-                -> MerkleRoot -- ^ Root of the merkle tree.
-buildMerkleRoot txs = calcHash (calcTreeHeight $ length txs) 0 txs
-
-hash2 :: Hash256 -> Hash256 -> Hash256
-hash2 a b = doubleHash256 $ encode a `BS.append` encode b
-
--- | Computes the hash of a specific node in a merkle tree.
-calcHash :: Int       -- ^ Height of the node in the merkle tree.
-         -> Int       -- ^ Position of the node (0 for the leftmost node).
-         -> [TxHash]  -- ^ Transaction hashes of the merkle tree (leaf nodes).
-         -> Hash256   -- ^ Hash of the node at the specified position.
-calcHash height pos txs
-    | height < 0 || pos < 0 = error "calcHash: Invalid parameters"
-    | height == 0 = getTxHash $ txs !! pos
-    | otherwise = hash2 left right
-  where
-    left = calcHash (height-1) (pos*2) txs
-    right | pos*2+1 < calcTreeWidth (length txs) (height-1) =
-                calcHash (height-1) (pos*2+1) txs
-          | otherwise = left
-
--- | Build a partial merkle tree.
-buildPartialMerkle
-    :: [(TxHash,Bool)]
-    -- ^ List of transactions hashes forming the leaves of the merkle tree
-    -- and a bool indicating if that transaction should be included in the
-    -- partial merkle tree.
-    -> (FlagBits, PartialMerkleTree)
-    -- ^ Flag bits (used to parse the partial merkle tree) and the
-    -- partial merkle tree.
-buildPartialMerkle hs = traverseAndBuild (calcTreeHeight $ length hs) 0 hs
-
-traverseAndBuild :: Int -> Int -> [(TxHash,Bool)]
-                 -> (FlagBits, PartialMerkleTree)
-traverseAndBuild height pos txs
-    | height < 0 || pos < 0 = error "traverseAndBuild: Invalid parameters"
-    | height == 0 || not match = ([match],[calcHash height pos t])
-    | otherwise = (match : lb ++ rb, lh ++ rh)
-  where
-    t = map fst txs
-    s = pos `shiftL` height
-    e = min (length txs) $ (pos+1) `shiftL` height
-    match = or $ map snd $ take (e-s) $ drop s txs
-    (lb,lh) = traverseAndBuild (height-1) (pos*2) txs
-    (rb,rh) | (pos*2+1) < calcTreeWidth (length txs) (height-1)
-                = traverseAndBuild (height-1) (pos*2+1) txs
-            | otherwise = ([],[])
-
-traverseAndExtract :: Int -> Int -> Int -> FlagBits -> PartialMerkleTree
-                   -> Maybe (MerkleRoot, [TxHash], Int, Int)
-traverseAndExtract height pos ntx flags hashes
-    | length flags == 0         = Nothing
-    | height == 0 || not match = leafResult
-    | isNothing leftM          = Nothing
-    | (pos*2+1) >= calcTreeWidth ntx (height-1) =
-        Just (hash2 lh lh, lm, lcf+1, lch)
-    | isNothing rightM         = Nothing
-    | otherwise =
-        Just (hash2 lh rh, lm ++ rm, lcf+rcf+1, lch+rch)
-  where
-    leafResult
-        | null hashes = Nothing
-        | otherwise = Just
-            (h, if height == 0 && match then [TxHash h] else [], 1, 1)
-    (match:fs) = flags
-    (h:_)     = hashes
-    leftM  = traverseAndExtract (height-1) (pos*2) ntx fs hashes
-    (lh,lm,lcf,lch) = fromMaybe e leftM
-    rightM = traverseAndExtract (height-1) (pos*2+1) ntx
-                (drop lcf fs) (drop lch hashes)
-    (rh,rm,rcf,rch) = fromMaybe e rightM
-    e = error "traverseAndExtract: unexpected error extracting a Maybe value"
-
--- | Extracts the matching hashes from a partial merkle tree. This will return
--- the list of transaction hashes that have been included (set to True) in
--- a call to 'buildPartialMerkle'.
-extractMatches :: FlagBits -- ^ Flag bits (produced by buildPartialMerkle).
-               -> PartialMerkleTree -- ^ Partial merkle tree.
-               -> Int -- ^ Number of transaction at height 0 (leaf nodes).
-               -> Either String (MerkleRoot, [TxHash])
-               -- ^ Merkle root and the list of matching transaction hashes.
-extractMatches flags hashes ntx
-    | ntx == 0 = Left $
-        "extractMatches: number of transactions can not be 0"
-    | ntx > maxBlockSize `div` 60 = Left $
-        "extractMatches: number of transactions excessively high"
-    | length hashes > ntx = Left $
-        "extractMatches: More hashes provided than the number of transactions"
-    | length flags < length hashes = Left $
-        "extractMatches: At least one bit per node and one bit per hash"
-    | isNothing resM = Left $
-        "extractMatches: traverseAndExtract failed"
-    | (nBitsUsed+7) `div` 8 /= (length flags+7) `div` 8 = Left $
-        "extractMatches: All bits were not consumed"
-    | nHashUsed /= length hashes = Left $
-        "extractMatches: All hashes were not consumed: " ++ (show nHashUsed)
-    | otherwise = return (merkRoot, matches)
-  where
-    resM = traverseAndExtract (calcTreeHeight ntx) 0 ntx flags hashes
-    (merkRoot, matches, nBitsUsed, nHashUsed) = fromMaybe e resM
-    e = error "extractMatches: unexpected error extracting a Maybe value"
-
-splitIn :: Int -> [a] -> [[a]]
-splitIn _ [] = []
-splitIn c xs = take c xs : (splitIn c $ drop c xs)
-
-boolsToWord8 :: [Bool] -> Word8
-boolsToWord8 [] = 0
-boolsToWord8 xs = foldl setBit 0 (map snd $ filter fst $ zip xs [0..7])
-
diff --git a/Network/Haskoin/Block/Types.hs b/Network/Haskoin/Block/Types.hs
deleted file mode 100644
--- a/Network/Haskoin/Block/Types.hs
+++ /dev/null
@@ -1,360 +0,0 @@
-module Network.Haskoin.Block.Types
-( Block(..)
-, BlockHeader
-, createBlockHeader
-, blockVersion
-, prevBlock
-, merkleRoot
-, blockTimestamp
-, blockBits
-, bhNonce
-, headerHash
-, BlockLocator
-, GetBlocks(..)
-, GetHeaders(..)
-, BlockHeaderCount
-, BlockHash(..)
-, blockHashToHex
-, hexToBlockHash
-, Headers(..)
-, decodeCompact
-, encodeCompact
-) where
-
-import           Control.DeepSeq                   (NFData, rnf)
-import           Control.Monad                     (forM_, liftM2, mzero,
-                                                    replicateM)
-import           Data.Aeson                        (FromJSON, ToJSON,
-                                                    Value (String), parseJSON,
-                                                    toJSON, withText)
-import           Data.Bits                         (shiftL, shiftR, (.&.),
-                                                    (.|.))
-import           Data.ByteString                   (ByteString)
-import qualified Data.ByteString                   as BS (length, reverse)
-import           Data.Maybe                        (fromMaybe)
-import           Data.Serialize                    (Serialize, encode, get, put)
-import           Data.Serialize.Get                (getWord32le, lookAhead,
-                                                    remaining, getByteString)
-import           Data.Serialize.Put                (Put, putWord32le)
-import           Data.String                       (IsString, fromString)
-import           Data.String.Conversions           (cs)
-import           Data.Word                         (Word32)
-import           Network.Haskoin.Crypto.Hash
-import           Network.Haskoin.Node.Types
-import           Network.Haskoin.Transaction.Types
-import           Network.Haskoin.Util
-import           Text.Read                         (lexP, parens, pfail,
-                                                    readPrec)
-import qualified Text.Read                         as Read (Lexeme (Ident, String))
-
--- | Data type describing a block in the bitcoin protocol. Blocks are sent in
--- response to 'GetData' messages that are requesting information from a
--- block hash.
-data Block =
-    Block {
-            -- | Header information for this block.
-            blockHeader     :: !BlockHeader
-            -- | List of transactions pertaining to this block.
-          , blockTxns       :: ![Tx]
-          } deriving (Eq, Show, Read)
-
-instance NFData Block where
-    rnf (Block h ts) = rnf h `seq` rnf ts
-
-instance Serialize Block where
-
-    get = do
-        header     <- get
-        (VarInt c) <- get
-        txs        <- replicateM (fromIntegral c) get
-        return $ Block header txs
-
-    put (Block h txs) = do
-        put h
-        put $ VarInt $ fromIntegral $ length txs
-        forM_ txs put
-
-newtype BlockHash = BlockHash { getBlockHash :: Hash256 }
-    deriving (Eq, Ord)
-
-instance NFData BlockHash where
-    rnf (BlockHash h) = rnf $ getHash256 h
-
-instance Show BlockHash where
-    showsPrec d h = showParen (d > 10) $
-        showString "BlockHash " . shows (blockHashToHex h)
-
-instance Read BlockHash where
-    readPrec = parens $ do
-        Read.Ident "BlockHash" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ hexToBlockHash $ cs str
-
-instance IsString BlockHash where
-    fromString = fromMaybe e . hexToBlockHash . cs where
-        e = error "Could not read block hash from hex string"
-
-instance Serialize BlockHash where
-    get = BlockHash <$> get
-    put = put . getBlockHash
-
-instance FromJSON BlockHash where
-    parseJSON = withText "Block hash" $ \t ->
-        maybe mzero return $ hexToBlockHash $ cs t
-
-instance ToJSON BlockHash where
-    toJSON = String . cs . blockHashToHex
-
-blockHashToHex :: BlockHash -> ByteString
-blockHashToHex (BlockHash h) = encodeHex $ BS.reverse $ getHash256 h
-
-hexToBlockHash :: ByteString -> Maybe BlockHash
-hexToBlockHash hex = do
-    bs <- BS.reverse <$> decodeHex hex
-    h <- bsToHash256 bs
-    return $ BlockHash h
-
--- | Data type recording information on a 'Block'. The hash of a block is
--- defined as the hash of this data structure. The block mining process
--- involves finding a partial hash collision by varying the nonce in the
--- 'BlockHeader' and/or additional randomness in the coinbase tx of this
--- 'Block'. Variations in the coinbase tx will result in different merkle
--- roots in the 'BlockHeader'.
-data BlockHeader =
-    BlockHeader {
-                  -- | Block version information, based on the version of the
-                  -- software creating this block.
-                  _blockVersion   :: !Word32
-                  -- | Hash of the previous block (parent) referenced by this
-                  -- block.
-                , _prevBlock      :: !BlockHash
-                  -- | Root of the merkle tree of all transactions pertaining
-                  -- to this block.
-                , _merkleRoot     :: !Hash256
-                  -- | Unix timestamp recording when this block was created
-                , _blockTimestamp :: !Word32
-                  -- | The difficulty target being used for this block
-                , _blockBits      :: !Word32
-                  -- | A random nonce used to generate this block. Additional
-                  -- randomness is included in the coinbase transaction of
-                  -- this block.
-                , _bhNonce        :: !Word32
-                  -- | Hash of the header
-                , _headerHash     :: !BlockHash
-                } deriving (Eq, Show, Read)
-
-createBlockHeader :: Word32 -> BlockHash -> Hash256
-                  -> Word32 -> Word32 -> Word32 -> BlockHeader
-createBlockHeader v p m t b n =
-    BlockHeader { _blockVersion   = v
-                , _prevBlock      = p
-                , _merkleRoot     = m
-                , _blockTimestamp = t
-                , _blockBits      = b
-                , _bhNonce        = n
-                , _headerHash     = BlockHash $ doubleHash256 $ encode bh
-                }
-  where
-    bh = BlockHeader { _blockVersion   = v
-                     , _prevBlock      = p
-                     , _merkleRoot     = m
-                     , _blockTimestamp = t
-                     , _blockBits      = b
-                     , _bhNonce        = n
-                     , _headerHash     = fromString $ replicate 64 '0'
-                     }
-
-blockVersion :: BlockHeader -> Word32
-blockVersion = _blockVersion
-
-prevBlock :: BlockHeader -> BlockHash
-prevBlock = _prevBlock
-
-merkleRoot :: BlockHeader -> Hash256
-merkleRoot = _merkleRoot
-
-blockTimestamp :: BlockHeader -> Word32
-blockTimestamp = _blockTimestamp
-
-blockBits :: BlockHeader -> Word32
-blockBits = _blockBits
-
-bhNonce :: BlockHeader -> Word32
-bhNonce = _bhNonce
-
-headerHash :: BlockHeader -> BlockHash
-headerHash = _headerHash
-
-instance NFData BlockHeader where
-    rnf (BlockHeader v p m t b n h) =
-        rnf v `seq` rnf p `seq` rnf m `seq`
-        rnf t `seq` rnf b `seq` rnf n `seq` rnf h
-
-instance Serialize BlockHeader where
-    get = do
-        start <- remaining
-        (v, p, m, t, b, n, end) <- lookAhead $ do
-            v <- getWord32le
-            p <- get
-            m <- get
-            t <- getWord32le
-            b <- getWord32le
-            n <- getWord32le
-            end <- remaining
-            return (v, p, m, t, b, n, end)
-        bs <- getByteString $ fromIntegral $ start - end
-        return $ BlockHeader
-            { _blockVersion   = v
-            , _prevBlock      = p
-            , _merkleRoot     = m
-            , _blockTimestamp = t
-            , _blockBits      = b
-            , _bhNonce        = n
-            , _headerHash     = BlockHash $ doubleHash256 bs
-            }
-
-    put (BlockHeader v p m bt bb n _) = do
-        putWord32le v
-        put         p
-        put         m
-        putWord32le bt
-        putWord32le bb
-        putWord32le n
-
-type BlockLocator = [BlockHash]
-
--- | Data type representing a GetBlocks message request. It is used in the
--- bitcoin protocol to retrieve blocks from a peer by providing it a
--- 'BlockLocator' object. The 'BlockLocator' is a sparse list of block hashes
--- from the caller node with the purpose of informing the receiving node
--- about the state of the caller's blockchain. The receiver node will detect
--- a wrong branch in the caller's main chain and send the caller appropriate
--- 'Blocks'. The response to a 'GetBlocks' message is an 'Inv' message
--- containing the list of block hashes pertaining to the request.
-data GetBlocks =
-    GetBlocks {
-                -- | The protocol version
-                getBlocksVersion  :: !Word32
-                -- | Block locator object. It is a list of block hashes from the
-                -- most recent block back to the genesis block. The list is
-                -- dense at first and sparse towards the end.
-              , getBlocksLocator  :: !BlockLocator
-                -- | Hash of the last desired block. If set to zero, the
-                -- maximum number of block hashes is returned (500).
-              , getBlocksHashStop :: !BlockHash
-              } deriving (Eq, Show, Read)
-
-instance NFData GetBlocks where
-    rnf (GetBlocks v l h) = rnf v `seq` rnf l `seq` rnf h
-
-instance Serialize GetBlocks where
-
-    get = GetBlocks <$> getWord32le
-                    <*> (repList =<< get)
-                    <*> get
-      where
-        repList (VarInt c) = replicateM (fromIntegral c) get
-
-    put (GetBlocks v xs h) = putGetBlockMsg v xs h
-
-putGetBlockMsg :: Word32 -> BlockLocator -> BlockHash -> Put
-putGetBlockMsg v xs h = do
-    putWord32le v
-    put $ VarInt $ fromIntegral $ length xs
-    forM_ xs put
-    put h
-
--- | Similar to the 'GetBlocks' message type but for retrieving block headers
--- only. The response to a 'GetHeaders' request is a 'Headers' message
--- containing a list of block headers pertaining to the request. A maximum of
--- 2000 block headers can be returned. 'GetHeaders' is used by thin (SPV)
--- clients to exclude block contents when synchronizing the blockchain.
-data GetHeaders =
-    GetHeaders {
-                 -- | The protocol version
-                 getHeadersVersion  :: !Word32
-                 -- | Block locator object. It is a list of block hashes from
-                 -- the most recent block back to the Genesis block. The list
-                 -- is dense at first and sparse towards the end.
-               , getHeadersBL       :: !BlockLocator
-                 -- | Hash of the last desired block header. When set to zero,
-                 -- the maximum number of block headers is returned (2000)
-               , getHeadersHashStop :: !BlockHash
-               } deriving (Eq, Show, Read)
-
-instance NFData GetHeaders where
-    rnf (GetHeaders v l h) = rnf v `seq` rnf l `seq` rnf h
-
-instance Serialize GetHeaders where
-
-    get = GetHeaders <$> getWord32le
-                     <*> (repList =<< get)
-                     <*> get
-      where
-        repList (VarInt c) = replicateM (fromIntegral c) get
-
-    put (GetHeaders v xs h) = putGetBlockMsg v xs h
-
--- | 'BlockHeader' type with a transaction count as 'VarInt'
-type BlockHeaderCount = (BlockHeader, VarInt)
-
--- | The 'Headers' type is used to return a list of block headers in
--- response to a 'GetHeaders' message.
-data Headers =
-    Headers {
-              -- | List of block headers with respective transaction counts
-              headersList :: ![BlockHeaderCount]
-            }
-    deriving (Eq, Show, Read)
-
-instance NFData Headers where
-    rnf (Headers l) = rnf l
-
-instance Serialize Headers where
-
-    get = Headers <$> (repList =<< get)
-      where
-        repList (VarInt c) = replicateM (fromIntegral c) action
-        action = liftM2 (,) get get
-
-    put (Headers xs) = do
-        put $ VarInt $ fromIntegral $ length xs
-        forM_ xs $ \(a,b) -> put a >> put b
-
--- | Decode the compact number used in the difficulty target of a block into an
--- Integer.
---
--- As described in the Satoshi reference implementation /src/bignum.h:
---
--- The "compact" format is a representation of a whole number N using an
--- unsigned 32bit number similar to a floating point format. The most
--- significant 8 bits are the unsigned exponent of base 256. This exponent can
--- be thought of as "number of bytes of N". The lower 23 bits are the mantissa.
--- Bit number 24 (0x800000) represents the sign of N.
---
--- >    N = (-1^sign) * mantissa * 256^(exponent-3)
-decodeCompact :: Word32 -> Integer
-decodeCompact c =
-    if neg then (-res) else res
-  where
-    size = fromIntegral $ c `shiftR` 24
-    neg  = (c .&. 0x00800000) /= 0
-    wrd  = c .&. 0x007fffff
-    res | size <= 3 = toInteger wrd `shiftR` (8*(3 - size))
-        | otherwise = toInteger wrd `shiftL` (8*(size - 3))
-
--- | Encode an Integer to the compact number format used in the difficulty
--- target of a block.
-encodeCompact :: Integer -> Word32
-encodeCompact i
-    | i < 0     = c3 .|. 0x00800000
-    | otherwise = c3
-  where
-    posi = abs i
-    s1 = BS.length $ integerToBS posi
-    c1 | s1 < 3    = posi `shiftL` (8*(3 - s1))
-       | otherwise = posi `shiftR` (8*(s1 - 3))
-    (s2,c2) | c1 .&. 0x00800000 /= 0  = (s1 + 1, c1 `shiftR` 8)
-            | otherwise               = (s1, c1)
-    c3 = fromIntegral $ c2 .|. (toInteger s2 `shiftL` 24)
-
diff --git a/Network/Haskoin/Constants.hs b/Network/Haskoin/Constants.hs
deleted file mode 100644
--- a/Network/Haskoin/Constants.hs
+++ /dev/null
@@ -1,256 +0,0 @@
-{-# OPTIONS_GHC -fno-cse -fno-full-laziness #-}
-{-|
-  Network specific constants
--}
-module Network.Haskoin.Constants
-( -- ** Data
-  Network(..)
-, prodnet
-, testnet3
-  -- ** Functions
-, switchToTestnet3
-, setNetwork
-, getNetwork
-  -- ** Network parameters
-, networkName
-, addrPrefix
-, scriptPrefix
-, secretPrefix
-, extPubKeyPrefix
-, extSecretPrefix
-, networkMagic
-, genesisHeader
-, maxBlockSize
-, maxSatoshi
-, haskoinUserAgent
-, defaultPort
-, allowMinDifficultyBlocks
-, powLimit
-, targetTimespan
-, targetSpacing
-, checkpoints
-) where
-
-import Data.Bits (shiftR)
-import Data.ByteString (ByteString)
-import qualified Data.ByteString.Char8 as C8 (concat, pack)
-import Data.IORef (IORef, newIORef, readIORef, writeIORef)
-import Data.Version (showVersion)
-import Data.Word (Word8, Word32, Word64)
-import Data.LargeWord (Word256)
-import Network.Haskoin.Block.Types
-import System.IO.Unsafe (unsafePerformIO)
-import Paths_haskoin_core (version)
-
-data Network = Network
-    { getNetworkName                :: !String
-    , getAddrPrefix                 :: !Word8
-    , getScriptPrefix               :: !Word8
-    , getSecretPrefix               :: !Word8
-    , getExtPubKeyPrefix            :: !Word32
-    , getExtSecretPrefix            :: !Word32
-    , getNetworkMagic               :: !Word32
-    , getGenesisHeader              :: !BlockHeader
-    , getMaxBlockSize               :: !Int
-    , getMaxSatoshi                 :: !Word64
-    , getHaskoinUserAgent           :: !ByteString
-    , getDefaultPort                :: !Int
-    , getAllowMinDifficultyBlocks   :: !Bool
-    , getPowLimit                   :: !Integer
-    , getTargetTimespan             :: !Word32
-    , getTargetSpacing              :: !Word32
-    , getCheckpoints                :: ![(Int, BlockHash)]
-    } deriving (Eq, Show, Read)
-
--- | Switch to Testnet3.  Do at start of program.
-switchToTestnet3 :: IO ()
-switchToTestnet3 = setNetwork testnet3
-
--- | Change network constants manually.  If switching to Testnet3, use
--- switchToTestnet3 instead.
-setNetwork :: Network -> IO ()
-setNetwork = writeIORef networkRef
-
-{-# NOINLINE networkRef #-}
--- | Use this if you want to change constants to something other than Testnet3.
-networkRef :: IORef Network
-networkRef = unsafePerformIO $ newIORef prodnet
-
-{-# NOINLINE getNetwork #-}
--- | Read current network constants record
-getNetwork :: Network
-getNetwork = unsafePerformIO $ readIORef networkRef
-
--- | Name of the bitcoin network
-networkName :: String
-networkName = getNetworkName getNetwork
-
--- | Prefix for base58 PubKey hash address
-addrPrefix :: Word8
-addrPrefix = getAddrPrefix getNetwork
-
--- | Prefix for base58 script hash address
-scriptPrefix :: Word8
-scriptPrefix = getScriptPrefix getNetwork
-
--- | Prefix for private key WIF format
-secretPrefix :: Word8
-secretPrefix = getSecretPrefix getNetwork
-
--- | Prefix for extended public keys (BIP32)
-extPubKeyPrefix :: Word32
-extPubKeyPrefix = getExtPubKeyPrefix getNetwork
-
--- | Prefix for extended private keys (BIP32)
-extSecretPrefix :: Word32
-extSecretPrefix = getExtSecretPrefix getNetwork
-
--- | Network magic bytes
-networkMagic :: Word32
-networkMagic = getNetworkMagic getNetwork
-
--- | Genesis block header information
-genesisHeader :: BlockHeader
-genesisHeader = getGenesisHeader getNetwork
-
--- | Maximum size of a block in bytes
-maxBlockSize :: Int
-maxBlockSize = getMaxBlockSize getNetwork
-
--- | Maximum number of satoshi
-maxSatoshi :: Word64
-maxSatoshi = getMaxSatoshi getNetwork
-
--- | User agent string
-haskoinUserAgent :: ByteString
-haskoinUserAgent = getHaskoinUserAgent getNetwork
-
--- | Default port
-defaultPort :: Int
-defaultPort = getDefaultPort getNetwork
-
--- | Allow relaxed difficulty transition rules
-allowMinDifficultyBlocks :: Bool
-allowMinDifficultyBlocks = getAllowMinDifficultyBlocks getNetwork
-
--- | Lower bound for the proof of work difficulty
-powLimit :: Integer
-powLimit = getPowLimit getNetwork
-
--- | Time between difficulty cycles (2 weeks on average)
-targetTimespan :: Word32
-targetTimespan = getTargetTimespan getNetwork
-
--- | Time between blocks (10 minutes per block)
-targetSpacing :: Word32
-targetSpacing = getTargetSpacing getNetwork
-
--- | Checkpoints to enfore
-checkpoints :: [(Int, BlockHash)]
-checkpoints = getCheckpoints getNetwork
-
-prodnet :: Network
-prodnet = Network
-    { getNetworkName = "prodnet"
-    , getAddrPrefix = 0
-    , getScriptPrefix = 5
-    , getSecretPrefix = 128
-    , getExtPubKeyPrefix = 0x0488b21e
-    , getExtSecretPrefix = 0x0488ade4
-    , getNetworkMagic = 0xf9beb4d9
-    , getGenesisHeader = createBlockHeader
-        0x01
-        "0000000000000000000000000000000000000000000000000000000000000000"
-        "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"
-        1231006505
-        486604799
-        2083236893
-        -- Hash 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
-    , getMaxBlockSize = 1000000
-    , getMaxSatoshi = 2100000000000000
-    , getHaskoinUserAgent = C8.concat
-        [ "/haskoin:"
-        , C8.pack $ showVersion version
-        , "/"
-        ]
-    , getDefaultPort = 8333
-    , getAllowMinDifficultyBlocks = False
-    , getPowLimit = fromIntegral (maxBound `shiftR` 32 :: Word256)
-    , getTargetTimespan = 14 * 24 * 60 * 60
-    , getTargetSpacing = 10 * 60
-    , getCheckpoints =
-        [ ( 11111
-          , "0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d"
-          )
-        , ( 33333
-          , "000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6"
-          )
-        , ( 74000
-          , "0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20"
-          )
-        , ( 105000
-          , "00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97"
-          )
-        , ( 134444
-          , "00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"
-          )
-        , ( 168000
-          , "000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763"
-          )
-        , ( 193000
-          , "000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317"
-          )
-        , ( 210000
-          , "000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e"
-          )
-        , ( 216116
-          , "00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e"
-          )
-        , ( 225430
-          , "00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932"
-          )
-        , ( 250000
-          , "000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214"
-          )
-        , ( 279000
-          , "0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40"
-          )
-        ]
-    }
-
-testnet3 :: Network
-testnet3 = Network
-    { getNetworkName = "testnet"
-    , getAddrPrefix = 111
-    , getScriptPrefix = 196
-    , getSecretPrefix = 239
-    , getExtPubKeyPrefix = 0x043587cf
-    , getExtSecretPrefix = 0x04358394
-    , getNetworkMagic = 0x0b110907
-    , getGenesisHeader = createBlockHeader
-        0x01
-        "0000000000000000000000000000000000000000000000000000000000000000"
-        "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"
-        1296688602
-        486604799
-        414098458
-        -- Hash 000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943
-    , getMaxBlockSize = 1000000
-    , getMaxSatoshi = 2100000000000000
-    , getHaskoinUserAgent = C8.concat
-        [ "/haskoin-testnet:"
-        , C8.pack $ showVersion version
-        , "/"
-        ]
-    , getDefaultPort = 18333
-    , getAllowMinDifficultyBlocks = True
-    , getPowLimit = fromIntegral (maxBound `shiftR` 32 :: Word256)
-    , getTargetTimespan = 14 * 24 * 60 * 60
-    , getTargetSpacing = 10 * 60
-    , getCheckpoints =
-        [ ( 546
-          , "000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70"
-          )
-        ]
-    }
-
diff --git a/Network/Haskoin/Crypto.hs b/Network/Haskoin/Crypto.hs
deleted file mode 100644
--- a/Network/Haskoin/Crypto.hs
+++ /dev/null
@@ -1,176 +0,0 @@
-{-|
-  This package provides the elliptic curve cryptography required for creating
-  and validating bitcoin transactions. It also provides SHA-256 and RIPEMD-160
-  hashing functions; as well as mnemonic keys from BIP-0039.
--}
-module Network.Haskoin.Crypto
-(
-  -- *Elliptic Curve Keys
-
-  -- **Public Keys
-  PubKey, PubKeyC, PubKeyU
-, makePubKey
-, makePubKeyG
-, makePubKeyC
-, makePubKeyU
-, toPubKeyG
-, eitherPubKey
-, maybePubKeyC
-, maybePubKeyU
-, derivePubKey
-, pubKeyAddr
-, tweakPubKeyC
-
-  -- **Private Keys
-, PrvKey, PrvKeyC, PrvKeyU
-, makePrvKey
-, makePrvKeyG
-, makePrvKeyC
-, makePrvKeyU
-, toPrvKeyG
-, eitherPrvKey
-, maybePrvKeyC
-, maybePrvKeyU
-, encodePrvKey
-, decodePrvKey
-, prvKeyPutMonad
-, prvKeyGetMonad
-, fromWif
-, toWif
-, tweakPrvKeyC
-
-  -- *ECDSA
-  -- **SecretT Monad
-  -- | The 'SecretT' monad is a monadic wrapper around  HMAC DRBG
-  -- (deterministic random byte generator) using SHA-256. The specification is
-  -- defined in
-  -- <http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf>. The
-  -- 'SecretT' monad is used to generate random private keys.
-, SecretT
-, withSource
-, getEntropy
-, genPrvKey
-
-  -- **Signatures
-  -- | Elliptic curve cryptography standards are defined in
-  -- <http://www.secg.org/sec1-v2.pdf>
-, Signature
-, signMsg
-, verifySig
-, isCanonicalHalfOrder
-, decodeDerSig
-, decodeStrictSig
-
-  -- *Hash functions
-, CheckSum32(getCheckSum32)
-, Hash512(getHash512)
-, Hash256(getHash256)
-, Hash160(getHash160)
-, bsToCheckSum32
-, bsToHash512
-, bsToHash256
-, bsToHash160
-, checkSum32
-, hash512
-, hash256
-, hash160
-, sha1
-, doubleHash256
-, hmac512
-, hmac256
-, split512
-, join512
-
-  -- *Base58 and Addresses
-, Address(..)
-, base58ToAddr
-, addrToBase58
-, encodeBase58
-, decodeBase58
-, encodeBase58Check
-, decodeBase58Check
-
-  -- *Mnemonic keys (BIP-0039)
-, Entropy
-, Mnemonic
-, Passphrase
-, Seed
-, toMnemonic
-, mnemonicToSeed
-
-  -- *Extended Keys
-, KeyIndex
-, ChainCode
-
-  -- **Extended Private Keys
-, XPrvKey(..)
-, makeXPrvKey
-, xPrvIsHard
-, xPrvChild
-, xPrvID
-, xPrvFP
-, xPrvExport
-, xPrvImport
-, xPrvWif
-
-  -- **Extended Public Keys
-, XPubKey(..)
-, deriveXPubKey
-, xPubIsHard
-, xPubChild
-, xPubID
-, xPubFP
-, xPubAddr
-, xPubExport
-, xPubImport
-
-  -- **Child key derivations
-, prvSubKey
-, pubSubKey
-, hardSubKey
-, prvSubKeys
-, pubSubKeys
-, hardSubKeys
-
-  -- ** Address derivations
-, deriveAddr
-, deriveAddrs
-, deriveMSAddr
-, deriveMSAddrs
-
-  -- ** Derivation paths
-, DerivPathI((:|), (:/), Deriv)
-, DerivPath
-, HardPath
-, SoftPath
-, derivePath
-, derivePubPath
-, toHard
-, toSoft
-, toGeneric
-, (++/)
-, pathToStr
-
-  -- ** Derivation path parsing
-, XKey(..)
-, ParsedPath(..)
-, parsePath
-, parseHard
-, parseSoft
-, applyPath
-
-  -- * Custom path address derivations
-, derivePathAddr
-, derivePathAddrs
-, derivePathMSAddr
-, derivePathMSAddrs
-
-) where
-
-import Network.Haskoin.Crypto.ECDSA
-import Network.Haskoin.Crypto.Keys
-import Network.Haskoin.Crypto.Hash
-import Network.Haskoin.Crypto.Base58
-import Network.Haskoin.Crypto.Mnemonic
-import Network.Haskoin.Crypto.ExtendedKeys
-
diff --git a/Network/Haskoin/Crypto/Base58.hs b/Network/Haskoin/Crypto/Base58.hs
deleted file mode 100644
--- a/Network/Haskoin/Crypto/Base58.hs
+++ /dev/null
@@ -1,156 +0,0 @@
-module Network.Haskoin.Crypto.Base58
-( Address(..)
-, addrToBase58
-, base58ToAddr
-, encodeBase58
-, decodeBase58
-, encodeBase58Check
-, decodeBase58Check
-) where
-
-import           Control.DeepSeq             (NFData, rnf)
-import           Control.Monad               (guard, mzero)
-import           Data.Aeson                  (FromJSON, ToJSON, Value (String),
-                                              parseJSON, toJSON, withText)
-import           Data.ByteString             (ByteString)
-import qualified Data.ByteString             as BS
-import qualified Data.ByteString.Char8       as C
-import           Data.Maybe                  (fromJust, fromMaybe, isJust,
-                                              listToMaybe)
-import           Data.Serialize              (Serialize, encode, get, put)
-import           Data.Serialize.Get          (getByteString, getWord8)
-import           Data.Serialize.Put          (putByteString, putWord8)
-import           Data.String                 (IsString, fromString)
-import           Data.String.Conversions     (cs)
-import           Network.Haskoin.Constants
-import           Network.Haskoin.Crypto.Hash
-import           Network.Haskoin.Util
-import           Numeric                     (readInt, showIntAtBase)
-import           Text.Read                   (lexP, parens, pfail, readPrec)
-import qualified Text.Read                   as Read (Lexeme (Ident, String))
-
-b58Data :: ByteString
-b58Data = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
-
-b58 :: Int -> Char
-b58 = C.index b58Data
-
-b58' :: Char -> Maybe Int
-b58' = flip C.elemIndex b58Data
-
-encodeBase58I :: Integer -> ByteString
-encodeBase58I i = cs $ showIntAtBase 58 b58 i ""
-
-decodeBase58I :: ByteString -> Maybe Integer
-decodeBase58I s =
-    case go of
-        Just (r,[]) -> Just r
-        _           -> Nothing
-  where
-    p = isJust . b58'
-    f = fromMaybe e . b58'
-    go = listToMaybe $ readInt 58 p f (cs s)
-    e = error "Could not decode base58"
-
--- | Encode a 'ByteString' to a base 58 representation.
-encodeBase58 :: ByteString -> ByteString
-encodeBase58 bs =
-    l `mappend` r
-  where
-    (z, b) = BS.span (== 0) bs
-    l = BS.replicate (BS.length z) (BS.index b58Data 0) -- preserve leading 0's
-    r | BS.null b = BS.empty
-      | otherwise = encodeBase58I $ bsToInteger b
-
--- | Decode a base58-encoded 'ByteString'. This can fail if the input
--- 'ByteString' contains invalid base58 characters such as 0, O, l, I.
-decodeBase58 :: ByteString -> Maybe ByteString
-decodeBase58 t =
-    BS.append prefix <$> r
-  where
-    (z, b)  = BS.span (== BS.index b58Data 0) t
-    prefix = BS.replicate (BS.length z) 0 -- preserve leading 1's
-    r | BS.null b = Just BS.empty
-      | otherwise = integerToBS <$> decodeBase58I b
-
--- | Computes a checksum for the input 'ByteString' and encodes the input and
--- the checksum to a base58 representation.
-encodeBase58Check :: ByteString -> ByteString
-encodeBase58Check bs = encodeBase58 $ BS.append bs (encode $ checkSum32 bs)
-
--- | Decode a base58-encoded string that contains a checksum. This function
--- returns 'Nothing' if the input string contains invalid base58 characters or
--- if the checksum fails.
-decodeBase58Check :: ByteString -> Maybe ByteString
-decodeBase58Check bs = do
-    rs <- decodeBase58 bs
-    let (res, chk) = BS.splitAt (BS.length rs - 4) rs
-    guard $ chk == encode (checkSum32 res)
-    return res
-
--- | Data type representing a Bitcoin address
-data Address
-    -- | Public Key Hash Address
-    = PubKeyAddress { getAddrHash :: !Hash160 }
-    -- | Script Hash Address
-    | ScriptAddress { getAddrHash :: !Hash160 }
-       deriving (Eq, Ord)
-
-instance Serialize Address where
-    get = do
-        pfx <- getWord8
-        bs <- getByteString 20
-        let addr = fromJust (bsToHash160 bs)
-        f pfx addr
-      where
-        f x a | x == addrPrefix   = return (PubKeyAddress a)
-              | x == scriptPrefix = return (ScriptAddress a)
-              | otherwise = fail "Does not recognize address prefix"
-    put (PubKeyAddress h) = do
-        putWord8 addrPrefix
-        putByteString (getHash160 h)
-    put (ScriptAddress h) = do
-        putWord8 scriptPrefix
-        putByteString (getHash160 h)
-
--- TODO: Test
-instance Show Address where
-    showsPrec d a = showParen (d > 10) $
-        showString "Address " . shows (addrToBase58 a)
-
--- TODO: Test
-instance Read Address where
-    readPrec = parens $ do
-        Read.Ident "Address" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ base58ToAddr $ cs str
-
--- TODO: Test
-instance IsString Address where
-    fromString =
-        fromMaybe e . base58ToAddr . cs
-      where
-        e = error "Could not decode bitcoin address"
-
-instance NFData Address where
-    rnf (PubKeyAddress h) = rnf h
-    rnf (ScriptAddress h) = rnf h
-
-instance FromJSON Address where
-    parseJSON = withText "Address" $
-        maybe mzero return . base58ToAddr . cs
-
-instance ToJSON Address where
-    toJSON = String . cs . addrToBase58
-
--- | Transforms an Address into a base58 encoded String
-addrToBase58 :: Address -> ByteString
-addrToBase58 = encodeBase58Check . encode
-
--- | Decodes an Address from a base58 encoded String. This function can fail
--- if the String is not properly encoded as base58 or the checksum fails.
-base58ToAddr :: ByteString -> Maybe Address
-base58ToAddr str = do
-    val <- decodeBase58Check str
-    decodeToMaybe val
-
diff --git a/Network/Haskoin/Crypto/ECDSA.hs b/Network/Haskoin/Crypto/ECDSA.hs
deleted file mode 100644
--- a/Network/Haskoin/Crypto/ECDSA.hs
+++ /dev/null
@@ -1,139 +0,0 @@
--- | ECDSA Signatures
-module Network.Haskoin.Crypto.ECDSA
-( SecretT
-, Signature(..)
-, withSource
-, getEntropy
-, signMsg
-, verifySig
-, genPrvKey
-, isCanonicalHalfOrder
-, decodeDerSig
-, decodeStrictSig
-) where
-
-import Numeric (showHex)
-
-import Control.DeepSeq (NFData, rnf)
-import Control.Monad (when, unless, guard)
-import Control.Monad.Trans (lift)
-import qualified Control.Monad.State as S
-    ( StateT
-    , evalStateT
-    , get, put
-    )
-
-import Data.Maybe (fromMaybe)
-import Data.Serialize (Serialize, get, put)
-import Data.Serialize.Put (putByteString, putByteString)
-import Data.Serialize.Get (getWord8, lookAhead, getByteString)
-import Data.ByteString (ByteString)
-import System.Entropy (getEntropy)
-
-import qualified Crypto.Secp256k1 as EC
-
-import Network.Haskoin.Constants
-import Network.Haskoin.Crypto.Hash
-import Network.Haskoin.Crypto.Keys
-
--- | Internal state of the 'SecretT' monad
-type SecretState m = (WorkingState, Int -> m ByteString)
-
--- | StateT monad stack tracking the internal state of HMAC DRBG
--- pseudo random number generator using SHA-256. The 'SecretT' monad is
--- run with the 'withSource' function by providing it a source of entropy.
-type SecretT m = S.StateT (SecretState m) m
-
--- | Run a 'SecretT' monad by providing it a source of entropy. You can
--- use 'getEntropy' or provide your own entropy source function.
-withSource :: Monad m => (Int -> m ByteString) -> SecretT m a -> m a
-withSource f m = do
-    seed  <- f 32 -- Read 256 bits from the random source
-    nonce <- f 16 -- Read 128 bits from the random source
-    let ws = hmacDRBGNew seed nonce haskoinUserAgent
-    S.evalStateT m (ws,f)
-
--- | Generate a new random 'EC.SecKey' value from the 'SecretT' monad. This
--- will invoke the HMAC DRBG routine. Of the internal entropy pool of the HMAC
--- DRBG was stretched too much, this function will reseed it.
-nextSecret :: Monad m => SecretT m EC.SecKey
-nextSecret = do
-    (ws, f) <- S.get
-    let (ws', randM) = hmacDRBGGen ws 32 haskoinUserAgent
-    case randM of
-        (Just rand) -> do
-            S.put (ws', f)
-            case EC.secKey rand of
-                Just key -> return key
-                Nothing  -> nextSecret
-        Nothing -> do
-            seed <- lift $ f 32 -- Read 256 bits to re-seed the PRNG
-            let ws0 = hmacDRBGRsd ws' seed haskoinUserAgent
-            S.put (ws0, f)
-            nextSecret
-
--- | Produce a new 'PrvKey' randomly from the 'SecretT' monad.
-genPrvKey :: Monad m => SecretT m PrvKey
-genPrvKey = makePrvKey <$> nextSecret
-
--- | Data type representing an ECDSA signature.
-newtype Signature = Signature { getSignature :: EC.Sig }
-    deriving (Read, Show, Eq)
-
-instance NFData Signature where
-    rnf (Signature s) = s `seq` ()
-
-hashToMsg :: Hash256 -> EC.Msg
-hashToMsg =
-    fromMaybe e . EC.msg . getHash256
-  where
-    e = error "Could not convert 32-byte hash to secp256k1 message"
-
--- <http://www.secg.org/sec1-v2.pdf Section 4.1.3>
--- | Sign a message
-signMsg :: Hash256 -> PrvKeyI c -> Signature
-signMsg h d = Signature $ EC.signMsg (prvKeySecKey d) (hashToMsg h)
-
--- | Verify an ECDSA signature
-verifySig :: Hash256 -> Signature -> PubKeyI c -> Bool
-verifySig h s q =
-    EC.verifySig p g m
-  where
-    (g, _) = EC.normalizeSig $ getSignature s
-    m = hashToMsg h
-    p = pubKeyPoint q
-
-instance Serialize Signature where
-    get = do
-        l <- lookAhead $ do
-            t <- getWord8
-            -- 0x30 is DER sequence type
-            unless (t == 0x30) $ fail $
-                "Bad DER identifier byte 0x" ++ showHex t ". Expecting 0x30"
-            l <- getWord8
-            when (l == 0x00) $ fail "Indeterminate form unsupported"
-            when (l >= 0x80) $ fail "Multi-octect length not supported"
-            return $ fromIntegral l
-        bs <- getByteString $ l + 2
-        case decodeDerSig bs of
-            Just s  -> return s
-            Nothing -> fail "Invalid signature"
-
-    put (Signature s) = putByteString $ EC.exportSig s
-
-isCanonicalHalfOrder :: Signature -> Bool
-isCanonicalHalfOrder = not . snd . EC.normalizeSig . getSignature
-
-decodeDerSig :: ByteString -> Maybe Signature
-decodeDerSig bs = Signature <$> EC.laxImportSig bs
-
-decodeStrictSig :: ByteString -> Maybe Signature
-decodeStrictSig bs = do
-    g <- EC.importSig bs
-    let compact = EC.exportCompactSig g
-    -- <http://www.secg.org/sec1-v2.pdf Section 4.1.4>
-    -- 4.1.4.1 (r and s can not be zero)
-    guard $ EC.getCompactSigR compact /= 0
-    guard $ EC.getCompactSigS compact /= 0
-    return $ Signature g
-
diff --git a/Network/Haskoin/Crypto/ExtendedKeys.hs b/Network/Haskoin/Crypto/ExtendedKeys.hs
deleted file mode 100644
--- a/Network/Haskoin/Crypto/ExtendedKeys.hs
+++ /dev/null
@@ -1,757 +0,0 @@
-module Network.Haskoin.Crypto.ExtendedKeys
-( XPubKey(..)
-, XPrvKey(..)
-, ChainCode
-, KeyIndex
-, DerivationException(..)
-, makeXPrvKey
-, deriveXPubKey
-, prvSubKey
-, pubSubKey
-, hardSubKey
-, xPrvIsHard
-, xPubIsHard
-, xPrvChild
-, xPubChild
-, xPubID
-, xPrvID
-, xPubFP
-, xPrvFP
-, xPubAddr
-, xPubExport
-, xPrvExport
-, xPubImport
-, xPrvImport
-, xPrvWif
-  -- Helpers
-, prvSubKeys
-, pubSubKeys
-, hardSubKeys
-, deriveAddr
-, deriveAddrs
-, deriveMSAddr
-, deriveMSAddrs
-, cycleIndex
-  -- Derivation paths
-, DerivPathI(..)
-, HardOrGeneric
-, GenericOrSoft
-, DerivPath
-, HardPath
-, SoftPath
-, Bip32PathIndex (..)
-, derivePath
-, derivePubPath
-, toHard
-, toSoft
-, toGeneric
-, (++/)
-, pathToStr
-
-  -- Derivation path parsing
-, XKey(..)
-, ParsedPath(..)
-, parsePath
-, parseHard
-, parseSoft
-, applyPath
-
-, derivePathAddr
-, derivePathAddrs
-, derivePathMSAddr
-, derivePathMSAddrs
-, concatBip32Segments
-) where
-
-import           Control.DeepSeq               (NFData, rnf)
-import           Control.Exception             (Exception, throw)
-import           Control.Monad                 (guard, mzero, unless, (<=<))
-import qualified Crypto.Secp256k1              as EC
-import           Data.Aeson                    (FromJSON, ToJSON,
-                                                Value (String), parseJSON,
-                                                toJSON, withText)
-import           Data.Bits                     (clearBit, setBit, testBit)
-import           Data.ByteString               (ByteString)
-import qualified Data.ByteString               as BS (append, take)
-import           Data.List                     (foldl')
-import           Data.List.Split               (splitOn)
-import           Data.Maybe                    (fromMaybe)
-import           Data.Serialize                (Serialize, decode, encode, get,
-                                                put)
-import           Data.Serialize.Get            (Get, getWord32be, getWord8)
-import           Data.Serialize.Put            (Put, putWord32be, putWord8,
-                                                runPut)
-import           Data.String                   (IsString, fromString)
-import           Data.String.Conversions       (cs)
-import           Data.Typeable                 (Typeable)
-import           Data.Word                     (Word32, Word8)
-import           Network.Haskoin.Constants
-import           Network.Haskoin.Crypto.Base58
-import           Network.Haskoin.Crypto.Hash
-import           Network.Haskoin.Crypto.Keys
-import           Network.Haskoin.Script.Parser
-import           Network.Haskoin.Util
-import           Text.Read                     (lexP, parens, pfail, readPrec)
-import qualified Text.Read                     as Read (Lexeme (Ident, String))
-
-{- See BIP32 for details: https://en.bitcoin.it/wiki/BIP_0032 -}
-
--- | A derivation exception is thrown in the very unlikely event that a
--- derivation is invalid.
-data DerivationException = DerivationException String
-    deriving (Eq, Read, Show, Typeable)
-
-instance Exception DerivationException
-
-type ChainCode = Hash256
-type KeyIndex = Word32
-
--- | Data type representing an extended BIP32 private key. An extended key
--- is a node in a tree of key derivations. It has a depth in the tree, a
--- parent node and an index to differentiate it from other siblings.
-data XPrvKey = XPrvKey
-    { xPrvDepth  :: !Word8     -- ^ Depth in the tree of key derivations.
-    , xPrvParent :: !Word32    -- ^ Fingerprint of the parent key.
-    , xPrvIndex  :: !KeyIndex  -- ^ Key derivation index.
-    , xPrvChain  :: !ChainCode -- ^ Chain code.
-    , xPrvKey    :: !PrvKeyC   -- ^ The private key of this extended key node.
-    } deriving (Eq)
-
-instance Ord XPrvKey where
-    compare k1 k2 = xPrvExport k1 `compare` xPrvExport k2
-
--- TODO: Test
-instance Show XPrvKey where
-    showsPrec d k = showParen (d > 10) $
-        showString "XPrvKey " . shows (xPrvExport k)
-
--- TODO: Test
-instance Read XPrvKey where
-    readPrec = parens $ do
-        Read.Ident "XPrvKey" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ xPrvImport $ cs str
-
--- TODO: Test
-instance IsString XPrvKey where
-    fromString =
-        fromMaybe e . xPrvImport . cs
-      where
-        e = error "Could not decode extended private key"
-
-instance NFData XPrvKey where
-    rnf (XPrvKey d p i c k) =
-        rnf d `seq` rnf p `seq` rnf i `seq` rnf c `seq` rnf k
-
-instance ToJSON XPrvKey where
-    toJSON = String . cs . xPrvExport
-
-instance FromJSON XPrvKey where
-    parseJSON = withText "xprvkey" $ maybe mzero return . xPrvImport . cs
-
--- | Data type representing an extended BIP32 public key.
-data XPubKey = XPubKey
-    { xPubDepth  :: !Word8     -- ^ Depth in the tree of key derivations.
-    , xPubParent :: !Word32    -- ^ Fingerprint of the parent key.
-    , xPubIndex  :: !KeyIndex  -- ^ Key derivation index.
-    , xPubChain  :: !ChainCode -- ^ Chain code.
-    , xPubKey    :: !PubKeyC   -- ^ The public key of this extended key node.
-    } deriving (Eq)
-
-instance Ord XPubKey where
-    compare k1 k2 = xPubExport k1 `compare` xPubExport k2
-
--- TODO: Test
-instance Show XPubKey where
-    showsPrec d k = showParen (d > 10) $
-        showString "XPubKey " . shows (xPubExport k)
-
--- TODO: Test
-instance Read XPubKey where
-    readPrec = parens $ do
-        Read.Ident "XPubKey" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ xPubImport $ cs str
-
--- TODO: Test
-instance IsString XPubKey where
-    fromString =
-        fromMaybe e . xPubImport . cs
-      where
-        e = error "Could not import extended public key"
-
-instance NFData XPubKey where
-    rnf (XPubKey d p i c k) =
-        rnf d `seq` rnf p `seq` rnf i `seq` rnf c `seq` rnf k
-
-instance ToJSON XPubKey where
-    toJSON = String . cs . xPubExport
-
-instance FromJSON XPubKey where
-    parseJSON = withText "xpubkey" $ maybe mzero return . xPubImport . cs
-
--- | Build a BIP32 compatible extended private key from a bytestring. This will
--- produce a root node (depth=0 and parent=0).
-makeXPrvKey :: ByteString -> XPrvKey
-makeXPrvKey bs =
-    XPrvKey 0 0 0 c k
-  where
-    (p, c) = split512 $ hmac512 "Bitcoin seed" bs
-    k     = fromMaybe err $ makePrvKeyC <$> EC.secKey (getHash256 p)
-    err   = throw $ DerivationException "Invalid seed"
-
--- | Derive an extended public key from an extended private key. This function
--- will preserve the depth, parent, index and chaincode fields of the extended
--- private keys.
-deriveXPubKey :: XPrvKey -> XPubKey
-deriveXPubKey (XPrvKey d p i c k) = XPubKey d p i c (derivePubKey k)
-
--- | Compute a private, soft child key derivation. A private soft derivation
--- will allow the equivalent extended public key to derive the public key for
--- this child. Given a parent key /m/ and a derivation index /i/, this function
--- will compute m\/i\/.
---
--- Soft derivations allow for more flexibility such as read-only wallets.
--- However, care must be taken not the leak both the parent extended public key
--- and one of the extended child private keys as this would compromise the
--- extended parent private key.
-prvSubKey :: XPrvKey  -- ^ Extended parent private key
-          -> KeyIndex -- ^ Child derivation index
-          -> XPrvKey  -- ^ Extended child private key
-prvSubKey xkey child
-    | child >= 0 && child < 0x80000000 =
-        XPrvKey (xPrvDepth xkey + 1) (xPrvFP xkey) child c k
-    | otherwise = error "Invalid child derivation index"
-  where
-    pK     = xPubKey $ deriveXPubKey xkey
-    msg    = BS.append (encode pK) (encode child)
-    (a, c) = split512 $ hmac512 (encode $ xPrvChain xkey) msg
-    k      = fromMaybe err $ tweakPrvKeyC (xPrvKey xkey) a
-    err    = throw $ DerivationException "Invalid prvSubKey derivation"
-
--- | Compute a public, soft child key derivation. Given a parent key /M/
--- and a derivation index /i/, this function will compute M\/i\/.
-pubSubKey :: XPubKey  -- ^ Extended Parent public key
-          -> KeyIndex -- ^ Child derivation index
-          -> XPubKey  -- ^ Extended child public key
-pubSubKey xKey child
-    | child >= 0 && child < 0x80000000 =
-        XPubKey (xPubDepth xKey + 1) (xPubFP xKey) child c pK
-    | otherwise = error "Invalid child derivation index"
-  where
-    msg    = BS.append (encode $ xPubKey xKey) (encode child)
-    (a, c) = split512 $ hmac512 (encode $ xPubChain xKey) msg
-    pK     = fromMaybe err $ tweakPubKeyC (xPubKey xKey) a
-    err    = throw $ DerivationException "Invalid pubSubKey derivation"
-
--- | Compute a hard child key derivation. Hard derivations can only be computed
--- for private keys. Hard derivations do not allow the parent public key to
--- derive the child public keys. However, they are safer as a breach of the
--- parent public key and child private keys does not lead to a breach of the
--- parent private key. Given a parent key /m/ and a derivation index /i/, this
--- function will compute m\/i'\/.
-hardSubKey :: XPrvKey  -- ^ Extended Parent private key
-           -> KeyIndex -- ^ Child derivation index
-           -> XPrvKey  -- ^ Extended child private key
-hardSubKey xkey child
-    | child >= 0 && child < 0x80000000 =
-        XPrvKey (xPrvDepth xkey + 1) (xPrvFP xkey) i c k
-    | otherwise = error "Invalid child derivation index"
-  where
-    i      = setBit child 31
-    msg    = BS.append (bsPadPrvKey $ xPrvKey xkey) (encode i)
-    (a, c) = split512 $ hmac512 (encode $ xPrvChain xkey) msg
-    k      = fromMaybe err $ tweakPrvKeyC (xPrvKey xkey) a
-    err    = throw $ DerivationException "Invalid hardSubKey derivation"
-
--- | Returns True if the extended private key was derived through a hard
--- derivation.
-xPrvIsHard :: XPrvKey -> Bool
-xPrvIsHard k = testBit (xPrvIndex k) 31
-
--- | Returns True if the extended public key was derived through a hard
--- derivation.
-xPubIsHard :: XPubKey -> Bool
-xPubIsHard k = testBit (xPubIndex k) 31
-
--- | Returns the derivation index of this extended private key without the hard
--- bit set.
-xPrvChild :: XPrvKey -> KeyIndex
-xPrvChild k = clearBit (xPrvIndex k) 31
-
--- | Returns the derivation index of this extended public key without the hard
--- bit set.
-xPubChild :: XPubKey -> KeyIndex
-xPubChild k = clearBit (xPubIndex k) 31
-
--- | Computes the key identifier of an extended private key.
-xPrvID :: XPrvKey -> Hash160
-xPrvID = xPubID . deriveXPubKey
-
--- | Computes the key identifier of an extended public key.
-xPubID :: XPubKey -> Hash160
-xPubID = hash160 . getHash256 . hash256 . encode . xPubKey
-
--- | Computes the key fingerprint of an extended private key.
-xPrvFP :: XPrvKey -> Word32
-xPrvFP =
-    either (const err) id . decode . BS.take 4 . getHash160 . xPrvID
-  where
-    err = error "Could not decode xPrvFP"
-
--- | Computes the key fingerprint of an extended public key.
-xPubFP :: XPubKey -> Word32
-xPubFP =
-    either (const err) id . decode . BS.take 4 . getHash160 . xPubID
-  where
-    err = error "Could not decode xPubFP"
-
--- | Computer the 'Address' of an extended public key.
-xPubAddr :: XPubKey -> Address
-xPubAddr = pubKeyAddr . xPubKey
-
--- | Exports an extended private key to the BIP32 key export format (base 58).
-xPrvExport :: XPrvKey -> ByteString
-xPrvExport = encodeBase58Check . encode
-
--- | Exports an extended public key to the BIP32 key export format (base 58).
-xPubExport :: XPubKey -> ByteString
-xPubExport = encodeBase58Check . encode
-
--- | Decodes a BIP32 encoded extended private key. This function will fail if
--- invalid base 58 characters are detected or if the checksum fails.
-xPrvImport :: ByteString -> Maybe XPrvKey
-xPrvImport = decodeToMaybe <=< decodeBase58Check
-
--- | Decodes a BIP32 encoded extended public key. This function will fail if
--- invalid base 58 characters are detected or if the checksum fails.
-xPubImport :: ByteString -> Maybe XPubKey
-xPubImport = decodeToMaybe <=< decodeBase58Check
-
--- | Export an extended private key to WIF (Wallet Import Format).
-xPrvWif :: XPrvKey -> ByteString
-xPrvWif = toWif . xPrvKey
-
-instance Serialize XPrvKey where
-
-    get = do
-        ver <- getWord32be
-        unless (ver == extSecretPrefix) $ fail $
-            "Get: Invalid version for extended private key"
-        dep <- getWord8
-        par <- getWord32be
-        idx <- getWord32be
-        chn <- get
-        prv <- getPadPrvKey
-        return $ XPrvKey dep par idx chn prv
-
-    put k = do
-        putWord32be  extSecretPrefix
-        putWord8     $ xPrvDepth k
-        putWord32be  $ xPrvParent k
-        putWord32be  $ xPrvIndex k
-        put          $ xPrvChain k
-        putPadPrvKey $ xPrvKey k
-
-instance Serialize XPubKey where
-
-    get = do
-        ver <- getWord32be
-        unless (ver == extPubKeyPrefix) $ fail $
-            "Get: Invalid version for extended public key"
-        dep <- getWord8
-        par <- getWord32be
-        idx <- getWord32be
-        chn <- get
-        pub <- get
-        return $ XPubKey dep par idx chn pub
-
-    put k = do
-        putWord32be extPubKeyPrefix
-        putWord8    $ xPubDepth k
-        putWord32be $ xPubParent k
-        putWord32be $ xPubIndex k
-        put         $ xPubChain k
-        put $ xPubKey k
-
-{- Derivation helpers -}
-
--- | Cyclic list of all private soft child key derivations of a parent key
--- starting from an offset index.
-prvSubKeys :: XPrvKey -> KeyIndex -> [(XPrvKey, KeyIndex)]
-prvSubKeys k = map (\i -> (prvSubKey k i, i)) . cycleIndex
-
--- | Cyclic list of all public soft child key derivations of a parent key
--- starting from an offset index.
-pubSubKeys :: XPubKey -> KeyIndex -> [(XPubKey, KeyIndex)]
-pubSubKeys k = map (\i -> (pubSubKey k i, i)) . cycleIndex
-
--- | Cyclic list of all hard child key derivations of a parent key starting
--- from an offset index.
-hardSubKeys :: XPrvKey -> KeyIndex -> [(XPrvKey, KeyIndex)]
-hardSubKeys k = map (\i -> (hardSubKey k i, i)) . cycleIndex
-
--- | Derive an address from a public key and an index. The derivation type
--- is a public, soft derivation.
-deriveAddr :: XPubKey -> KeyIndex -> (Address, PubKeyC)
-deriveAddr k i =
-    (xPubAddr key, xPubKey key)
-  where
-    key = pubSubKey k i
-
--- | Cyclic list of all addresses derived from a public key starting from an
--- offset index. The derivation types are public, soft derivations.
-deriveAddrs :: XPubKey -> KeyIndex -> [(Address, PubKeyC, KeyIndex)]
-deriveAddrs k =
-    map f . cycleIndex
-  where
-    f i = let (a, key) = deriveAddr k i in (a, key, i)
-
--- | Derive a multisig address from a list of public keys, the number of
--- required signatures (m) and a derivation index. The derivation type is a
--- public, soft derivation.
-deriveMSAddr :: [XPubKey] -> Int -> KeyIndex -> (Address, RedeemScript)
-deriveMSAddr keys m i =
-    (scriptAddr rdm, rdm)
-  where
-    rdm = sortMulSig $ PayMulSig k m
-    k   = map (toPubKeyG . xPubKey . flip pubSubKey i) keys
-
--- | Cyclic list of all multisig addresses derived from a list of public keys,
--- a number of required signatures (m) and starting from an offset index. The
--- derivation type is a public, soft derivation.
-deriveMSAddrs :: [XPubKey] -> Int -> KeyIndex
-              -> [(Address, RedeemScript, KeyIndex)]
-deriveMSAddrs keys m =
-    map f . cycleIndex
-  where
-    f i = let (a, rdm) = deriveMSAddr keys m i in (a, rdm, i)
-
-cycleIndex :: KeyIndex -> [KeyIndex]
-cycleIndex i
-    | i == 0         = cycle [0..0x7fffffff]
-    | i < 0x80000000 = cycle $ [i..0x7fffffff] ++ [0..(i-1)]
-    | otherwise      = error $ "cycleIndex: invalid index " ++ (show i)
-
-{- Derivation Paths -}
-
-data Hard
-data Generic
-data Soft
-
-type HardPath = DerivPathI Hard
-type DerivPath = DerivPathI Generic
-type SoftPath = DerivPathI Soft
-
-class HardOrGeneric a
-instance HardOrGeneric Hard
-instance HardOrGeneric Generic
-
-class GenericOrSoft a
-instance GenericOrSoft Generic
-instance GenericOrSoft Soft
-
--- | Data type representing a derivation path. Two constructors are provided
--- for specifying soft or hard derivations. The path /0/1'/2 for example can be
--- expressed as Deriv :/ 0 :| 1 :/ 2. The HardOrGeneric and GenericOrSoft type
--- classes are used to constrain the valid values for the phantom type t. If
--- you mix hard (:|) and soft (:/) paths, the only valid type for t is Generic.
--- Otherwise, t can be Hard if you only have hard derivation or Soft if you
--- only have soft derivations.
---
--- Using this type is as easy as writing the required derivation like in these
--- example:
--- Deriv :/ 0 :/ 1 :/ 2 :: SoftPath
--- Deriv :| 0 :| 1 :| 2 :: HardPath
--- Deriv :| 0 :/ 1 :/ 2 :: DerivPath
-data DerivPathI t where
-    (:|)  :: HardOrGeneric t => !(DerivPathI t) -> !KeyIndex -> DerivPathI t
-    (:/)  :: GenericOrSoft t => !(DerivPathI t) -> !KeyIndex -> DerivPathI t
-    Deriv :: DerivPathI t
-
-instance NFData (DerivPathI t) where
-    rnf p = case p of
-        next :| i -> rnf i `seq` rnf next
-        next :/ i -> rnf i `seq` rnf next
-        Deriv     -> ()
-
-instance Eq (DerivPathI t) where
-    (nextA :| iA) == (nextB :| iB) = iA == iB && nextA == nextB
-    (nextA :/ iA) == (nextB :/ iB) = iA == iB && nextA == nextB
-    Deriv         == Deriv         = True
-    _             == _             = False
-
--- TODO: Test
-pathToStr :: DerivPathI t -> String
-pathToStr p =
-    case p of
-        next :| i -> concat [ pathToStr next, "/", show i, "'" ]
-        next :/ i -> concat [ pathToStr next, "/", show i ]
-        Deriv     -> ""
-
-toHard :: DerivPathI t -> Maybe HardPath
-toHard p = case p of
-    next :| i -> (:| i) <$> toHard next
-    Deriv     -> Just Deriv
-    _         -> Nothing
-
-toSoft :: DerivPathI t -> Maybe SoftPath
-toSoft p = case p of
-    next :/ i -> (:/ i) <$> toSoft next
-    Deriv     -> Just Deriv
-    _         -> Nothing
-
-toGeneric :: DerivPathI t -> DerivPath
-toGeneric p = case p of
-    next :/ i -> (toGeneric next) :/ i
-    next :| i -> (toGeneric next) :| i
-    Deriv     -> Deriv
-
--- | Append two derivation paths together. The result will be a mixed
--- derivation path.
-(++/) :: DerivPathI t1 -> DerivPathI t2 -> DerivPath
-(++/) p1 p2 =
-    go id (toGeneric p2) $ toGeneric p1
-  where
-    go f p = case p of
-        next :/ i -> go (f . (:/ i)) $ toGeneric next
-        next :| i -> go (f . (:| i)) $ toGeneric next
-        _ -> f
-
--- | Derive a private key from a derivation path
-derivePath :: DerivPathI t -> XPrvKey -> XPrvKey
-derivePath = go id
-  where
-    -- Build the full derivation function starting from the end
-    go f p = case p of
-        next :| i -> go (f . flip hardSubKey i) next
-        next :/ i -> go (f . flip prvSubKey i) next
-        _ -> f
-
--- | Derive a public key from a soft derivation path
-derivePubPath :: SoftPath -> XPubKey -> XPubKey
-derivePubPath = go id
-  where
-    -- Build the full derivation function starting from the end
-    go f p = case p of
-        next :/ i -> go (f . flip pubSubKey i) next
-        _ -> f
-
--- TODO: Test
-instance Show DerivPath where
-    showsPrec d p = showParen (d > 10) $
-        showString "DerivPath " . shows (pathToStr p)
-
--- TODO: Test
-instance Show HardPath where
-    showsPrec d p = showParen (d > 10) $
-        showString "HardPath " . shows (pathToStr p)
-
--- TODO: Test
-instance Show SoftPath where
-    showsPrec d p = showParen (d > 10) $
-        showString "SoftPath " . shows (pathToStr p)
-
--- TODO: Test
-instance Read DerivPath where
-    readPrec = parens $ do
-        Read.Ident "DerivPath" <- lexP
-        Read.String str <- lexP
-        maybe pfail (return . getParsedPath) $ parsePath str
-
--- TODO: Test
-instance Read HardPath where
-    readPrec = parens $ do
-        Read.Ident "HardPath" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ parseHard str
-
--- TODO: Test
-instance Read SoftPath where
-    readPrec = parens $ do
-        Read.Ident "SoftPath" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ parseSoft str
-
--- TODO: Test
-instance IsString ParsedPath where
-    fromString =
-        fromMaybe e . parsePath
-      where
-        e = error "Could not parse derivation path"
-
--- TODO: Test
-instance IsString DerivPath where
-    fromString =
-        getParsedPath . fromMaybe e . parsePath
-      where
-        e = error "Could not parse derivation path"
-
--- TODO: Test
-instance IsString HardPath where
-    fromString =
-        fromMaybe e . parseHard
-      where
-        e = error "Could not parse hard derivation path"
-
--- TODO: Test
-instance IsString SoftPath where
-    fromString =
-        fromMaybe e . parseSoft
-      where
-        e = error "Could not parse soft derivation path"
-
-instance FromJSON ParsedPath where
-    parseJSON = withText "ParsedPathPath" $ \str -> case parsePath $ cs str of
-        Just p -> return p
-        _      -> mzero
-
-instance FromJSON DerivPath where
-    parseJSON = withText "DerivPath" $ \str -> case parsePath $ cs str of
-        Just p -> return $ getParsedPath p
-        _      -> mzero
-
-instance FromJSON HardPath where
-    parseJSON = withText "HardPath" $ \str -> case parseHard $ cs str of
-        Just p -> return p
-        _      -> mzero
-
-instance FromJSON SoftPath where
-    parseJSON = withText "SoftPath" $ \str -> case parseSoft $ cs str of
-        Just p -> return p
-        _      -> mzero
-
-instance ToJSON (DerivPathI t) where
-    toJSON = String . cs . pathToStr
-
-instance ToJSON ParsedPath where
-    toJSON (ParsedPrv p)   = String . cs . ("m" ++) . pathToStr $ p
-    toJSON (ParsedPub p)   = String . cs . ("M" ++) . pathToStr $ p
-    toJSON (ParsedEmpty p) = String . cs . ("" ++) . pathToStr $ p
-
-{- Parsing derivation paths of the form m/1/2'/3 or M/1/2'/3 -}
-
-data ParsedPath = ParsedPrv   { getParsedPath :: !DerivPath }
-                | ParsedPub   { getParsedPath :: !DerivPath }
-                | ParsedEmpty { getParsedPath :: !DerivPath }
-  deriving (Read, Show, Eq)
--- | Parse derivation path string for extended key.
--- Forms: “m/0'/2”, “M/2/3/4”.
-parsePath :: String -> Maybe ParsedPath
-parsePath str = do
-    res <- concatBip32Segments <$> mapM parseBip32PathIndex xs
-    case x of
-        "m" -> Just $ ParsedPrv res
-        "M" -> Just $ ParsedPub res
-        ""  -> Just $ ParsedEmpty res
-        _   -> Nothing
-  where
-    (x : xs) = splitOn "/" str
-
-concatBip32Segments :: [Bip32PathIndex] -> DerivPath
-concatBip32Segments xs = foldl' appendBip32Segment Deriv xs
-
-
-appendBip32Segment :: DerivPath -> Bip32PathIndex  -> DerivPath
-appendBip32Segment d (Bip32SoftIndex i) = d :/ i
-appendBip32Segment d (Bip32HardIndex i) = d :| i
-
-
-parseBip32PathIndex :: String -> Maybe Bip32PathIndex
-parseBip32PathIndex segment = case reads segment of
-    [(i, "" )] -> guard (is31Bit i) >> ( return $ Bip32SoftIndex i )
-    [(i, "'")] -> guard (is31Bit i) >> ( return $ Bip32HardIndex i )
-    _ -> Nothing
-
-
-data Bip32PathIndex = Bip32HardIndex KeyIndex | Bip32SoftIndex KeyIndex
-  deriving (Read,Show,Eq)
-
-is31Bit :: (Integral a) => a -> Bool
-is31Bit i = (i >=0 && i < 0x80000000)
-
-
--- Helper function to parse a hard path
-parseHard :: String -> Maybe HardPath
-parseHard = toHard . getParsedPath <=< parsePath
-
--- Helper function to parse a soft path
-parseSoft :: String -> Maybe SoftPath
-parseSoft = toSoft . getParsedPath <=< parsePath
-
-data XKey = XPrv { getXPrvKey :: !XPrvKey }
-          | XPub { getXPubKey :: !XPubKey }
-    deriving (Eq, Show)
-
--- | Apply a parsed path to an extended key to derive the new key defined in the
--- path. If the path starts with m/, a private key will be returned and if the
--- path starts with M/, a public key will be returned.
--- Private derivations on a public key, and public derivations with a hard segment,
--- return an error value.
-applyPath :: ParsedPath -> XKey -> Either String XKey
-applyPath path key = case (path, key) of
-    (ParsedPrv _, XPrv k) -> return $ XPrv $ derivPrvF k
-    (ParsedPrv _, XPub _) -> Left "applyPath: Invalid public key"
-    (ParsedPub _, XPrv k) -> return $ XPub $ deriveXPubKey $ derivPrvF k
-    (ParsedPub _, XPub k) -> derivPubFE >>= \f -> return $ XPub $ f k
-    -- For empty parsed paths, we take a hint from the provided key
-    (ParsedEmpty _, XPrv k) -> return $ XPrv $ derivPrvF k
-    (ParsedEmpty _, XPub k) -> derivPubFE >>= \f -> return $ XPub $ f k
-  where
-    derivPrvF  = goPrv id $ getParsedPath path
-    derivPubFE = goPubE id $ getParsedPath path
-    -- Build the full private derivation function starting from the end
-    goPrv f p = case p of
-        next :| i -> goPrv (f . flip hardSubKey i) next
-        next :/ i -> goPrv (f . flip prvSubKey i) next
-        Deriv     -> f
-    -- Build the full public derivation function starting from the end
-    goPubE f p = case p of
-        next :/ i -> goPubE (f . flip pubSubKey i) next
-        Deriv     -> Right f
-        _         -> Left "applyPath: Invalid hard derivation"
-
-{- Helpers for derivation paths and addresses -}
-
--- | Derive an address from a given parent path.
-derivePathAddr :: XPubKey -> SoftPath -> KeyIndex -> (Address, PubKeyC)
-derivePathAddr key path i = deriveAddr (derivePubPath path key) i
-
--- | Cyclic list of all addresses derived from a given parent path and starting
--- from the given offset index.
-derivePathAddrs :: XPubKey -> SoftPath -> KeyIndex
-                -> [(Address, PubKeyC, KeyIndex)]
-derivePathAddrs key path i = deriveAddrs (derivePubPath path key) i
-
--- | Derive a multisig address from a given parent path. The number of required
--- signatures (m in m of n) is also needed.
-derivePathMSAddr :: [XPubKey] -> SoftPath -> Int -> KeyIndex
-                 -> (Address, RedeemScript)
-derivePathMSAddr keys path m i =
-    deriveMSAddr (map (derivePubPath path) keys) m i
-
--- | Cyclic list of all multisig addresses derived from a given parent path and
--- starting from the given offset index. The number of required signatures
--- (m in m of n) is also needed.
-derivePathMSAddrs :: [XPubKey] -> SoftPath -> Int -> KeyIndex
-                  -> [(Address, RedeemScript, KeyIndex)]
-derivePathMSAddrs keys path m i =
-    deriveMSAddrs (map (derivePubPath path) keys) m i
-
-{- Utilities for extended keys -}
-
--- De-serialize HDW-specific private key
-getPadPrvKey :: Get PrvKeyC
-getPadPrvKey = do
-    pad <- getWord8
-    unless (pad == 0x00) $ fail $
-        "Private key must be padded with 0x00"
-    prvKeyGetMonad makePrvKeyC -- Compressed version
-
--- Serialize HDW-specific private key
-putPadPrvKey :: PrvKeyC -> Put
-putPadPrvKey p = putWord8 0x00 >> prvKeyPutMonad p
-
-bsPadPrvKey :: PrvKeyC -> ByteString
-bsPadPrvKey = runPut . putPadPrvKey
-
diff --git a/Network/Haskoin/Crypto/Hash.hs b/Network/Haskoin/Crypto/Hash.hs
deleted file mode 100644
--- a/Network/Haskoin/Crypto/Hash.hs
+++ /dev/null
@@ -1,316 +0,0 @@
--- | Hashing functions and HMAC DRBG definition
-module Network.Haskoin.Crypto.Hash
-( Hash512(getHash512)
-, Hash256(getHash256)
-, Hash160(getHash160)
-, CheckSum32(getCheckSum32)
-, bsToHash512
-, bsToHash256
-, bsToHash160
-, hash512
-, hash256
-, hash160
-, sha1
-, doubleHash256
-, bsToCheckSum32
-, checkSum32
-, hmac512
-, hmac256
-, split512
-, join512
-, hmacDRBGNew
-, hmacDRBGUpd
-, hmacDRBGRsd
-, hmacDRBGGen
-, WorkingState
-) where
-
-import Crypto.Hash
-    ( Digest
-    , SHA512
-    , SHA256
-    , SHA1
-    , RIPEMD160
-    , hash
-    )
-import Crypto.MAC.HMAC (hmac)
-
-import Control.DeepSeq (NFData, rnf)
-import Control.Monad ((<=<), guard)
-import Data.Byteable (toBytes)
-import Data.Maybe (fromMaybe)
-import Data.Word (Word16)
-import Data.String (IsString, fromString)
-import Data.String.Conversions (cs)
-import Text.Read (Lexeme(String, Ident), readPrec, lexP, parens, pfail)
-import Data.Serialize (Serialize, get, put)
-import Data.Serialize.Get (getByteString)
-import Data.Serialize.Put (putByteString)
-
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as BS
-    ( null
-    , append
-    , cons
-    , concat
-    , take
-    , empty
-    , length
-    , replicate
-    , splitAt
-    )
-
-import Network.Haskoin.Util
-
-newtype CheckSum32 = CheckSum32 { getCheckSum32 :: ByteString }
-    deriving (Eq, Ord)
-
-newtype Hash512 = Hash512 { getHash512 :: ByteString }
-    deriving (Eq, Ord)
-
-newtype Hash256 = Hash256 { getHash256 :: ByteString }
-    deriving (Eq, Ord)
-
-newtype Hash160 = Hash160 { getHash160 :: ByteString }
-    deriving (Eq, Ord)
-
-
-instance NFData CheckSum32 where
-    rnf (CheckSum32 bs) = rnf bs
-
-instance Show CheckSum32 where
-    showsPrec d (CheckSum32 bs) = showParen (d > 10) $
-        showString "CheckSum32 " . shows (encodeHex bs)
-
-instance Read CheckSum32 where
-    readPrec = parens $ do
-        Ident "CheckSum32" <- lexP
-        String str <- lexP
-        maybe pfail return $ bsToCheckSum32 =<< decodeHex (cs str)
-
-instance IsString CheckSum32 where
-    fromString =
-        fromMaybe e . (bsToCheckSum32 <=< decodeHex) . cs
-      where
-        e = error "Could not decode checksum"
-
-instance Serialize CheckSum32 where
-    get = CheckSum32 <$> getByteString 4
-    put (CheckSum32 bs) = putByteString bs
-
-
-instance NFData Hash512 where
-    rnf (Hash512 bs) = rnf bs
-
-instance Show Hash512 where
-    showsPrec d (Hash512 bs) = showParen (d > 10) $
-        showString "Hash512 " . shows (encodeHex bs)
-
-instance Read Hash512 where
-    readPrec = parens $ do
-        Ident "Hash512" <- lexP
-        String str <- lexP
-        maybe pfail return $ bsToHash512 =<< decodeHex (cs str)
-
-instance IsString Hash512 where
-    fromString =
-        fromMaybe e . (bsToHash512 <=< decodeHex) . cs
-      where
-        e = error "Could not decode 64-byte hash"
-
-instance Serialize Hash512 where
-    get = Hash512 <$> getByteString 64
-    put (Hash512 bs) = putByteString bs
-
-
-instance NFData Hash256 where
-    rnf (Hash256 bs) = rnf bs
-
-instance Show Hash256 where
-    showsPrec d (Hash256 bs) = showParen (d > 10) $
-        showString "Hash256 " . shows (encodeHex bs)
-
-instance Read Hash256 where
-    readPrec = parens $ do
-        Ident "Hash256" <- lexP
-        String str <- lexP
-        maybe pfail return $ bsToHash256 =<< decodeHex (cs str)
-
-instance IsString Hash256 where
-    fromString =
-        fromMaybe e . (bsToHash256 <=< decodeHex) . cs
-      where
-        e = error "Could not decode 32-byte hash"
-
-instance Serialize Hash256 where
-    get = Hash256 <$> getByteString 32
-    put (Hash256 bs) = putByteString bs
-
-
-instance NFData Hash160 where
-    rnf (Hash160 bs) = rnf bs
-
-instance Show Hash160 where
-    showsPrec d (Hash160 bs) = showParen (d > 10) $
-        showString "Hash160 " . shows (encodeHex bs)
-
-instance Read Hash160 where
-    readPrec = parens $ do
-        Ident "Hash160" <- lexP
-        String str <- lexP
-        maybe pfail return $ bsToHash160 =<< decodeHex (cs str)
-
-instance IsString Hash160 where
-    fromString =
-        fromMaybe e . (bsToHash160 <=< decodeHex) . cs
-      where
-        e = error "Could not decode 20-byte hash"
-
-instance Serialize Hash160 where
-    get = Hash160 <$> getByteString 20
-    put (Hash160 bs) = putByteString bs
-
-
-bsToHash512 :: ByteString -> Maybe Hash512
-bsToHash512 bs = guard (BS.length bs == 64) >> return (Hash512 bs)
-
-bsToHash256 :: ByteString -> Maybe Hash256
-bsToHash256 bs = guard (BS.length bs == 32) >> return (Hash256 bs)
-
-bsToHash160 :: ByteString -> Maybe Hash160
-bsToHash160 bs = guard (BS.length bs == 20) >> return (Hash160 bs)
-
--- | Compute SHA-512.
-hash512 :: ByteString -> Hash512
-hash512 = Hash512 . (toBytes :: Digest SHA512 -> ByteString) . hash
-
--- | Compute SHA-256.
-hash256 :: ByteString -> Hash256
-hash256 = Hash256 . (toBytes :: Digest SHA256 -> ByteString) . hash
-
--- | Compute RIPEMD-160.
-hash160 :: ByteString -> Hash160
-hash160 = Hash160 . (toBytes :: Digest RIPEMD160 -> ByteString) . hash
-
--- | Compute SHA1
-sha1 :: ByteString -> Hash160
-sha1 = Hash160 . (toBytes :: Digest SHA1 -> ByteString) . hash
-
--- | Compute two rounds of SHA-256.
-doubleHash256 :: ByteString -> Hash256
-doubleHash256 = hash256 . getHash256 . hash256
-
-{- CheckSum -}
-
-bsToCheckSum32 :: ByteString -> Maybe CheckSum32
-bsToCheckSum32 bs = guard (BS.length bs == 4) >> return (CheckSum32 bs)
-
--- | Computes a 32 bit checksum.
-checkSum32 :: ByteString -> CheckSum32
-checkSum32 bs =
-    CheckSum32 $ BS.take 4 bs'
-  where
-    Hash256 bs' = doubleHash256 bs
-
-{- HMAC -}
-
--- | Computes HMAC over SHA-512.
-hmac512 :: ByteString -> ByteString -> Hash512
-hmac512 key msg =
-    Hash512 $ hmac f 128 key msg
-  where
-    f bs = let Hash512 bs' = hash512 bs in bs'
-
--- | Computes HMAC over SHA-256.
-hmac256 :: ByteString -> ByteString -> Hash256
-hmac256 key msg =
-    Hash256 $ hmac f 64 key msg
-  where
-    f bs = let Hash256 bs' = hash256 bs in bs'
-
--- | Split a 'Hash512' into a pair of 'Hash256'.
-split512 :: Hash512 -> (Hash256, Hash256)
-split512 (Hash512 bs) =
-    (Hash256 a, Hash256 b)
-  where
-    (a, b) = BS.splitAt 32 bs
-
--- | Join a pair of 'Hash256' into a 'Hash512'.
-join512 :: (Hash256, Hash256) -> Hash512
-join512 (Hash256 a, Hash256 b) = Hash512 $ a `BS.append` b
-
-
-{- 10.1.2 HMAC_DRBG with HMAC-SHA256
-   http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
-   Constants are based on recommentations in Appendix D section 2 (D.2)
--}
-
-type WorkingState    = (ByteString, ByteString, Word16)
-type AdditionalInput = ByteString
-type ProvidedData    = ByteString
-type EntropyInput    = ByteString
-type Nonce           = ByteString
-type PersString      = ByteString
-
--- 10.1.2.2 HMAC DRBG Update FUnction
-hmacDRBGUpd :: ProvidedData -> ByteString -> ByteString
-            -> (ByteString, ByteString)
-hmacDRBGUpd info k0 v0
-    | BS.null info = (k1, v1)        -- 10.1.2.2.3
-    | otherwise    = (k2, v2)        -- 10.1.2.2.6
-  where
-    -- 10.1.2.2.1
-    Hash256 k1 = hmac256 k0 $ v0 `BS.append` (0 `BS.cons` info)
-    -- 10.1.2.2.2
-    Hash256 v1 = hmac256 k1 v0
-    -- 10.1.2.2.4
-    Hash256 k2 = hmac256 k1 $ v1 `BS.append` (1 `BS.cons` info)
-    -- 10.1.2.2.5
-    Hash256 v2 = hmac256 k2 v1
-
--- 10.1.2.3 HMAC DRBG Instantiation
-hmacDRBGNew :: EntropyInput -> Nonce -> PersString -> WorkingState
-hmacDRBGNew seed nonce info
-    | (BS.length seed + BS.length nonce) * 8 < 384  = error $
-        "Entropy + nonce input length must be at least 384 bit"
-    | (BS.length seed + BS.length nonce) * 8 > 1000 = error $
-        "Entropy + nonce input length can not be greater than 1000 bit"
-    | BS.length info * 8 > 256  = error $
-        "Maximum personalization string length is 256 bit"
-    | otherwise                = (k1, v1, 1)         -- 10.1.2.3.6
-  where
-    s        = BS.concat [seed, nonce, info] -- 10.1.2.3.1
-    k0       = BS.replicate 32 0             -- 10.1.2.3.2
-    v0       = BS.replicate 32 1             -- 10.1.2.3.3
-    (k1,v1)  = hmacDRBGUpd s k0 v0           -- 10.1.2.3.4
-
--- 10.1.2.4 HMAC DRBG Reseeding
-hmacDRBGRsd :: WorkingState -> EntropyInput -> AdditionalInput -> WorkingState
-hmacDRBGRsd (k, v, _) seed info
-    | BS.length seed * 8 < 256 = error $
-        "Entropy input length must be at least 256 bit"
-    | BS.length seed * 8 > 1000 = error $
-        "Entropy input length can not be greater than 1000 bit"
-    | otherwise   = (k0, v0, 1)             -- 10.1.2.4.4
-  where
-    s        = seed `BS.append` info -- 10.1.2.4.1
-    (k0, v0) = hmacDRBGUpd s k v     -- 10.1.2.4.2
-
--- 10.1.2.5 HMAC DRBG Generation
-hmacDRBGGen :: WorkingState -> Word16 -> AdditionalInput
-            -> (WorkingState, Maybe ByteString)
-hmacDRBGGen (k0, v0, c0) bytes info
-    | bytes * 8 > 7500 = error "Maximum bits per request is 7500"
-    | c0 > 10000       = ((k0, v0, c0), Nothing)  -- 10.1.2.5.1
-    | otherwise        = ((k2, v3, c1), Just res) -- 10.1.2.5.8
-  where
-    (k1, v1)  | BS.null info = (k0, v0)
-              | otherwise    = hmacDRBGUpd info k0 v0   -- 10.1.2.5.2
-    (tmp, v2) = go (fromIntegral bytes) k1 v1 BS.empty -- 10.1.2.5.3/4
-    res       = BS.take (fromIntegral bytes) tmp       -- 10.1.2.5.5
-    (k2, v3)  = hmacDRBGUpd info k1 v2                 -- 10.1.2.5.6
-    c1        = c0 + 1                                 -- 10.1.2.5.7
-    go l k v acc | BS.length acc >= l = (acc,v)
-                 | otherwise = let vn = getHash256 $ hmac256 k v
-                               in go l k vn (acc `BS.append` vn)
-
diff --git a/Network/Haskoin/Crypto/Keys.hs b/Network/Haskoin/Crypto/Keys.hs
deleted file mode 100644
--- a/Network/Haskoin/Crypto/Keys.hs
+++ /dev/null
@@ -1,401 +0,0 @@
-module Network.Haskoin.Crypto.Keys
-( PubKeyI(pubKeyCompressed, pubKeyPoint)
-, PubKey, PubKeyC, PubKeyU
-, makePubKey
-, makePubKeyG
-, makePubKeyC
-, makePubKeyU
-, toPubKeyG
-, eitherPubKey
-, maybePubKeyC
-, maybePubKeyU
-, derivePubKey
-, pubKeyAddr
-, tweakPubKeyC
-, PrvKeyI(prvKeyCompressed, prvKeySecKey)
-, PrvKey, PrvKeyC, PrvKeyU
-, makePrvKey
-, makePrvKeyG
-, makePrvKeyC
-, makePrvKeyU
-, toPrvKeyG
-, eitherPrvKey
-, maybePrvKeyC
-, maybePrvKeyU
-, encodePrvKey
-, decodePrvKey
-, prvKeyPutMonad
-, prvKeyGetMonad
-, fromWif
-, toWif
-, tweakPrvKeyC
-) where
-
-import           Control.Applicative           ((<|>))
-import           Control.DeepSeq               (NFData, rnf)
-import           Control.Monad                 (guard, mzero, (<=<))
-import qualified Crypto.Secp256k1              as EC
-import           Data.Aeson                    (FromJSON, ToJSON,
-                                                Value (String), parseJSON,
-                                                toJSON, withText)
-import           Data.ByteString               (ByteString)
-import qualified Data.ByteString               as BS (cons, elem, head, init,
-                                                      last, length, pack, snoc,
-                                                      tail)
-import           Data.Maybe                    (fromMaybe)
-import           Data.Serialize                (Serialize, encode, get, put)
-import           Data.Serialize.Get            (Get, getByteString)
-import           Data.Serialize.Put            (Put, putByteString)
-import           Data.String                   (IsString, fromString)
-import           Data.String.Conversions       (cs)
-import           Network.Haskoin.Constants
-import           Network.Haskoin.Crypto.Base58
-import           Network.Haskoin.Crypto.Hash
-import           Network.Haskoin.Util
-import           Text.Read                     (lexP, parens, pfail, readPrec)
-import qualified Text.Read                     as Read (Lexeme (Ident, String))
-
-data Generic
-data Compressed
-data Uncompressed
-
--- | Elliptic curve public key type. Two constructors are provided for creating
--- compressed and uncompressed public keys from a Point. The use of compressed
--- keys is preferred as it produces shorter keys without compromising security.
--- Uncompressed keys are supported for backwards compatibility.
-type PubKey = PubKeyI Generic
-type PubKeyC = PubKeyI Compressed
-type PubKeyU = PubKeyI Uncompressed
-
--- Internal type for public keys
-data PubKeyI c = PubKeyI
-    { pubKeyPoint      :: !EC.PubKey
-    , pubKeyCompressed :: !Bool
-    } deriving (Eq)
-
--- TODO: Test
-instance Show PubKey where
-    showsPrec d k = showParen (d > 10) $
-        showString "PubKey " . shows (encodeHex $ encode k)
-
--- TODO: Test
-instance Show PubKeyC where
-    showsPrec d k = showParen (d > 10) $
-        showString "PubKeyC " . shows (encodeHex $ encode k)
-
--- TODO: Test
-instance Show PubKeyU where
-    showsPrec d k = showParen (d > 10) $
-        showString "PubKeyU " . shows (encodeHex $ encode k)
-
--- TODO: Test
-instance Read PubKey where
-    readPrec = parens $ do
-        Read.Ident "PubKey" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ decodeToMaybe <=< decodeHex $ cs str
-
--- TODO: Test
-instance Read PubKeyC where
-    readPrec = parens $ do
-        Read.Ident "PubKeyC" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ decodeToMaybe <=< decodeHex $ cs str
-
--- TODO: Test
-instance Read PubKeyU where
-    readPrec = parens $ do
-        Read.Ident "PubKeyU" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ decodeToMaybe <=< decodeHex $ cs str
-
--- TODO: Test
-instance IsString PubKey where
-    fromString str =
-        fromMaybe e $ decodeToMaybe <=< decodeHex $ cs str
-      where
-        e = error "Could not decode public key"
-
-instance IsString PubKeyC where
-    fromString str =
-        fromMaybe e $ decodeToMaybe <=< decodeHex $ cs str
-      where
-        e = error "Could not decode compressed public key"
-
-instance IsString PubKeyU where
-    fromString str =
-        fromMaybe e $ decodeToMaybe <=< decodeHex $ cs str
-      where
-        e = error "Could not decode uncompressed public key"
-
-instance NFData (PubKeyI c) where
-    rnf (PubKeyI p c) = p `seq` rnf c
-
-instance ToJSON PubKey where
-    toJSON = String . cs . encodeHex . encode
-
-instance FromJSON PubKey where
-    parseJSON = withText "PubKey" $
-        maybe mzero return . (decodeToMaybe =<<) . decodeHex . cs
-
-instance ToJSON PubKeyC where
-    toJSON = String . cs . encodeHex . encode
-
-instance FromJSON PubKeyC where
-    parseJSON = withText "PubKeyC" $
-        maybe mzero return . (decodeToMaybe =<<) . decodeHex . cs
-
-instance ToJSON PubKeyU where
-    toJSON = String . cs . encodeHex . encode
-
-instance FromJSON PubKeyU where
-    parseJSON = withText "PubKeyU" $
-        maybe mzero return . (decodeToMaybe =<<) . decodeHex . cs
-
--- Constructors for public keys
-makePubKey :: EC.PubKey -> PubKey
-makePubKey p = PubKeyI p True
-
-makePubKeyG :: Bool -> EC.PubKey -> PubKey
-makePubKeyG c p = PubKeyI p c
-
-makePubKeyC :: EC.PubKey -> PubKeyC
-makePubKeyC p = PubKeyI p True
-
-makePubKeyU :: EC.PubKey -> PubKeyU
-makePubKeyU p = PubKeyI p False
-
-toPubKeyG :: PubKeyI c -> PubKey
-toPubKeyG (PubKeyI p c) = makePubKeyG c p
-
-eitherPubKey :: PubKeyI c -> Either PubKeyU PubKeyC
-eitherPubKey pk
-    | pubKeyCompressed pk = Right $ makePubKeyC $ pubKeyPoint pk
-    | otherwise           = Left  $ makePubKeyU $ pubKeyPoint pk
-
-maybePubKeyC :: PubKeyI c -> Maybe PubKeyC
-maybePubKeyC pk
-    | pubKeyCompressed pk = Just $ makePubKeyC $ pubKeyPoint pk
-    | otherwise           = Nothing
-
-maybePubKeyU :: PubKeyI c -> Maybe PubKeyU
-maybePubKeyU pk
-    | not (pubKeyCompressed pk) = Just $ makePubKeyU $ pubKeyPoint pk
-    | otherwise                 = Nothing
-
--- | Derives a public key from a private key. This function will preserve
--- information on key compression ('PrvKey' becomes 'PubKey' and 'PrvKeyU'
--- becomes 'PubKeyU')
-derivePubKey :: PrvKeyI c -> PubKeyI c
-derivePubKey (PrvKeyI d c) = PubKeyI (EC.derivePubKey d) c
-
-instance Serialize PubKey where
-    get =
-        (toPubKeyG <$> getC) <|> (toPubKeyG <$> getU)
-      where
-        getC = get :: Get (PubKeyI Compressed)
-        getU = get :: Get (PubKeyI Uncompressed)
-
-    put pk = case eitherPubKey pk of
-        Left k  -> put k
-        Right k -> put k
-
-instance Serialize PubKeyC where
-    get = do
-        bs <- getByteString 33
-        guard $ BS.head bs `BS.elem` BS.pack [0x02, 0x03]
-        maybe mzero return $ makePubKeyC <$> EC.importPubKey bs
-
-    put pk = putByteString $ EC.exportPubKey True $ pubKeyPoint pk
-
-instance Serialize PubKeyU where
-    get = do
-        bs <- getByteString 65
-        guard $ BS.head bs == 0x04
-        maybe mzero return $ makePubKeyU <$> EC.importPubKey bs
-
-    put pk = putByteString $ EC.exportPubKey False $ pubKeyPoint pk
-
--- | Computes an 'Address' from a public key
-pubKeyAddr :: Serialize (PubKeyI c) => PubKeyI c -> Address
-pubKeyAddr = PubKeyAddress . hash160 . getHash256 . hash256 . encode
-
--- | Tweak a compressed public key
-tweakPubKeyC :: PubKeyC -> Hash256 -> Maybe PubKeyC
-tweakPubKeyC pub h =
-    makePubKeyC <$> (EC.tweakAddPubKey point =<< tweak)
-  where
-    point = pubKeyPoint pub
-    tweak = EC.tweak $ getHash256 h
-
-{- Private Keys -}
-
--- | Elliptic curve private key type. Two constructors are provided for creating
--- compressed or uncompressed private keys. Compression information is stored
--- in private key WIF formats and needs to be preserved to generate the correct
--- addresses from the corresponding public key.
-
--- Internal private key type
-data PrvKeyI c = PrvKeyI
-    { prvKeySecKey     :: !EC.SecKey
-    , prvKeyCompressed :: !Bool
-    } deriving (Eq)
-
-instance NFData (PrvKeyI c) where
-    rnf (PrvKeyI s b) = s `seq` b `seq` ()
-
--- TODO: Test
-instance Show PrvKey where
-    showsPrec d k = showParen (d > 10) $
-        showString "PrvKey " . shows (toWif k)
-
--- TODO: Test
-instance Show PrvKeyC where
-    showsPrec d k = showParen (d > 10) $
-        showString "PrvKeyC " . shows (toWif k)
-
--- TODO: Test
-instance Show PrvKeyU where
-    showsPrec d k = showParen (d > 10) $
-        showString "PrvKeyU " . shows (toWif k)
-
--- TODO: Test
-instance Read PrvKey where
-    readPrec = parens $ do
-        Read.Ident "PrvKey" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ fromWif $ cs str
-
--- TODO: Test
-instance Read PrvKeyC where
-    readPrec = parens $ do
-        Read.Ident "PrvKeyC" <- lexP
-        Read.String str <- lexP
-        key <- maybe pfail return $ fromWif $ cs str
-        case eitherPrvKey key of
-            Left _  -> pfail
-            Right k -> return k
-
--- TODO: Test
-instance Read PrvKeyU where
-    readPrec = parens $ do
-        Read.Ident "PrvKeyU" <- lexP
-        Read.String str <- lexP
-        key <- maybe pfail return $ fromWif $ cs str
-        case eitherPrvKey key of
-            Left k  -> return k
-            Right _ -> pfail
-
--- TODO: Test
-instance IsString PrvKey where
-    fromString str =
-        fromMaybe e $ fromWif $ cs str
-      where
-        e = error "Could not decode WIF"
-
--- TODO: Test
-instance IsString PrvKeyC where
-    fromString str =
-        case eitherPrvKey key of
-            Left _  -> undefined
-            Right k -> k
-      where
-        key = fromMaybe e $ fromWif $ cs str
-        e = error "Could not decode WIF"
-
--- TODO: Test
-instance IsString PrvKeyU where
-    fromString str =
-        case eitherPrvKey key of
-            Left k  -> k
-            Right _ -> undefined
-      where
-        key = fromMaybe e $ fromWif $ cs str
-        e = error "Could not decode WIF"
-
-type PrvKey = PrvKeyI Generic
-type PrvKeyC = PrvKeyI Compressed
-type PrvKeyU = PrvKeyI Uncompressed
-
-makePrvKeyI :: Bool -> EC.SecKey -> PrvKeyI c
-makePrvKeyI c d = PrvKeyI d c
-
-makePrvKey :: EC.SecKey -> PrvKey
-makePrvKey d = makePrvKeyI True d
-
-makePrvKeyG :: Bool -> EC.SecKey -> PrvKey
-makePrvKeyG = makePrvKeyI
-
-makePrvKeyC :: EC.SecKey -> PrvKeyC
-makePrvKeyC d = makePrvKeyI True d
-
-makePrvKeyU :: EC.SecKey -> PrvKeyU
-makePrvKeyU d = makePrvKeyI False d
-
-toPrvKeyG :: PrvKeyI c -> PrvKey
-toPrvKeyG (PrvKeyI d c) = PrvKeyI d c
-
-eitherPrvKey :: PrvKeyI c -> Either PrvKeyU PrvKeyC
-eitherPrvKey (PrvKeyI d compressed)
-    | compressed = Right $ PrvKeyI d compressed
-    | otherwise  = Left  $ PrvKeyI d compressed
-
-maybePrvKeyC :: PrvKeyI c -> Maybe PrvKeyC
-maybePrvKeyC (PrvKeyI d compressed)
-    | compressed = Just $ PrvKeyI d compressed
-    | otherwise  = Nothing
-
-maybePrvKeyU :: PrvKeyI c -> Maybe PrvKeyU
-maybePrvKeyU (PrvKeyI d compressed)
-    | not compressed = Just $ PrvKeyI d compressed
-    | otherwise      = Nothing
-
--- | Serialize private key as 32-byte big-endian 'ByteString'
-encodePrvKey :: PrvKeyI c -> ByteString
-encodePrvKey (PrvKeyI d _) = EC.getSecKey d
-
--- | Deserialize private key as 32-byte big-endian 'ByteString'
-decodePrvKey :: (EC.SecKey -> PrvKeyI c) -> ByteString -> Maybe (PrvKeyI c)
-decodePrvKey f bs = f <$> EC.secKey bs
-
-prvKeyGetMonad :: (EC.SecKey -> PrvKeyI c) -> Get (PrvKeyI c)
-prvKeyGetMonad f = do
-    bs <- getByteString 32
-    fromMaybe err $ return <$> f <$> EC.secKey bs
-  where
-    err = fail "Get: Invalid private key"
-
-prvKeyPutMonad :: PrvKeyI c -> Put
-prvKeyPutMonad (PrvKeyI k _) = putByteString $ EC.getSecKey k
-
--- | Decodes a private key from a WIF encoded 'ByteString'. This function can
--- fail if the input string does not decode correctly as a base 58 string or if
--- the checksum fails.
--- <http://en.bitcoin.it/wiki/Wallet_import_format>
-fromWif :: ByteString -> Maybe PrvKey
-fromWif wif = do
-    bs <- decodeBase58Check wif
-    -- Check that this is a private key
-    guard (BS.head bs == secretPrefix)
-    case BS.length bs of
-        33 -> do               -- Uncompressed format
-            makePrvKeyG False <$> EC.secKey (BS.tail bs)
-        34 -> do               -- Compressed format
-            guard $ BS.last bs == 0x01
-            makePrvKeyG True <$> EC.secKey (BS.tail $ BS.init bs)
-        _  -> Nothing          -- Bad length
-
--- | Encodes a private key into WIF format
-toWif :: PrvKeyI c -> ByteString
-toWif (PrvKeyI k c) = encodeBase58Check $ BS.cons secretPrefix $
-    if c then EC.getSecKey k `BS.snoc` 0x01 else EC.getSecKey k
-
-
--- | Tweak a private key
-tweakPrvKeyC :: PrvKeyC -> Hash256 -> Maybe PrvKeyC
-tweakPrvKeyC key h =
-    makePrvKeyC <$> (EC.tweakAddSecKey sec =<< tweak)
-  where
-    sec   = prvKeySecKey key
-    tweak = EC.tweak $ getHash256 h
-
diff --git a/Network/Haskoin/Crypto/Mnemonic.hs b/Network/Haskoin/Crypto/Mnemonic.hs
deleted file mode 100644
--- a/Network/Haskoin/Crypto/Mnemonic.hs
+++ /dev/null
@@ -1,499 +0,0 @@
--- | Mnemonic keys (BIP-39). Only the English dictionary in the BIP is
--- supported.
-module Network.Haskoin.Crypto.Mnemonic
-(
-  -- * Data types
-  Entropy
-, Mnemonic
-, Passphrase
-, Seed
-
-  -- * Entropy encoding and decoding
-, toMnemonic
-, fromMnemonic
-
-  -- * Generating 512-bit seeds
-, mnemonicToSeed
-
-  -- * Helper functions
-, getBits
-) where
-
-import Control.Monad (when)
-import qualified Crypto.Hash.SHA256 as SHA256
-import Crypto.PBKDF.ByteString (sha512PBKDF2)
-import Data.Bits ((.&.), shiftL, shiftR)
-import Data.ByteString (ByteString)
-import qualified Data.ByteString.Char8 as C (unwords, words)
-import Data.String.Conversions (cs)
-import qualified Data.ByteString as BS
-import qualified Data.Map.Strict as M
-import Data.List
-import Data.Maybe
-import Data.Vector ((!), Vector)
-import qualified Data.Vector as V
-import Network.Haskoin.Util
-
-type Entropy = ByteString
-type Mnemonic = ByteString
-type Passphrase = ByteString
-type Seed = ByteString
-type Checksum = ByteString
-
--- | Provide intial entropy as a 'ByteString' of length multiple of 4 bytes.
--- Output a mnemonic sentence.
-toMnemonic :: Entropy -> Either String Mnemonic
-toMnemonic ent = do
-    when (remainder /= 0) $
-        Left "toMnemonic: entropy must be multiples of 4 bytes"
-    when (cs_len > 16) $
-        Left "toMnemonic: maximum entropy is 64 bytes (512 bits)"
-    return ms
-  where
-    (cs_len, remainder) = BS.length ent `quotRem` 4
-    c = calcCS cs_len ent
-    indices = bsToIndices $ ent `BS.append` c
-    ms = C.unwords $ map (wl!) indices
-
--- | Revert 'toMnemonic'. Do not use this to generate seeds. Instead use
--- 'mnemonicToSeed'. This outputs the original entropy used to generate a
--- mnemonic.
-fromMnemonic :: Mnemonic -> Either String Entropy
-fromMnemonic ms = do
-    when (word_count > 48) $
-        Left $ "fromMnemonic: too many words: " ++ show word_count
-    when (word_count `mod` 3 /= 0) $
-        Left $ "fromMnemonic: wrong number of words:" ++ show word_count
-    ms_bs <- indicesToBS =<< getIndices ms_words
-    let (ms_ent, ms_cs) = BS.splitAt (ent_len * 4) ms_bs
-        ms_cs_num = numCS cs_len ms_cs
-        ent_cs_num = numCS cs_len $ calcCS cs_len ms_ent
-    when (ent_cs_num /= ms_cs_num) $
-        Left $ "fromMnemonic: checksum failed: " ++ sh ent_cs_num ms_cs_num
-    return ms_ent
-  where
-    ms_words = C.words ms
-    word_count = length ms_words
-    (ent_len, cs_len) = (word_count * 11) `quotRem` 32
-    sh cs_a cs_b = show cs_a ++ " /= " ++ show cs_b
-
-calcCS :: Int -> Entropy -> Checksum
-calcCS len = getBits len . SHA256.hash
-
-numCS :: Int -> Entropy -> Integer
-numCS len =
-    shiftCS . bsToInteger
-  where
-    shiftCS = case 8 - len `mod` 8 of
-        0 -> id
-        x -> flip shiftR x
-
--- | Turn any sequence of characters into a 512-bit seed.  Does not have to be
--- a mnemonic sentence generated from 'toMnemonic'.  Use 'mnemonicToSeed' to
--- get a seed from a mnemonic sentence.  Warning: Does not perform NFKD
--- normalization.
-anyToSeed :: Passphrase -> Mnemonic -> Seed
-anyToSeed pf ms =
-    sha512PBKDF2 ms ("mnemonic" `mappend` pf) 2048 64
-
--- | Get a 512-bit seed from a mnemonic sentence.  Will calculate checksum.
--- Passphrase can be used to protect the mnemonic.  Use an empty string as
--- passphrase if none is required.
-mnemonicToSeed :: Passphrase -> Mnemonic -> Either String Seed
-mnemonicToSeed pf ms = do
-    ent <- fromMnemonic ms
-    mnm <- toMnemonic ent
-    return $ anyToSeed pf mnm
-
--- | Obtain 'Int' bits from beginning of 'ByteString'. Resulting 'ByteString'
--- will be smallest required to hold that many bits, padded with zeroes to the
--- right.
-getBits :: Int -> ByteString -> ByteString
-getBits b bs
-    | r == 0 = BS.take q bs
-    | otherwise = i `BS.snoc` l
-  where
-    (q, r) = b `quotRem` 8
-    s = (BS.take (q + 1) bs)
-    i = BS.init s
-    l = BS.last s .&. (0xff `shiftL` (8 - r))    -- zero unneeded bits
-
--- | Get indices of words in word list.
-getIndices :: [ByteString] -> Either String [Int]
-getIndices ws
-    | null n = return $ catMaybes i
-    | otherwise = Left $ "getIndices: words not found: " ++ cs w
-  where
-    i = map (`M.lookup` wl') ws
-    n = elemIndices Nothing i
-    w = C.unwords $ map (ws!!) n
-
-indicesToBS :: [Int] -> Either String ByteString
-indicesToBS is = do
-    when lrg $ Left "indicesToBS: index larger or equal than 2048"
-    return . pad . integerToBS $ foldl' f 0 is `shiftL` shift_width
-  where
-    lrg = not . isNothing $ find (>= 2048) is
-    (q, r) = (length is * 11) `quotRem` 8
-    shift_width = if r == 0 then 0 else 8 - r
-    bl = if r == 0 then q else q + 1   -- length of resulting ByteString
-    pad bs = BS.append (BS.replicate (bl - BS.length bs) 0x00) bs
-    f acc x = (acc `shiftL` 11) + fromIntegral x
-
-bsToIndices :: ByteString -> [Int]
-bsToIndices bs =
-    reverse . go q $ bsToInteger bs `shiftR` r
-  where
-    (q, r) = (BS.length bs * 8) `quotRem` 11
-    go 0 _ = []
-    go n i = (fromIntegral $ i `mod` 2048) : go (n - 1) (i `shiftR` 11)
-
-wl' :: M.Map ByteString Int
-wl' = V.ifoldr' (\i w m -> M.insert w i m) M.empty wl
-
--- | Standard English dictionary from BIP-39 specification.
-wl :: Vector ByteString
-wl = V.fromListN 2048
-    [ "abandon", "ability", "able", "about", "above", "absent"
-    , "absorb", "abstract", "absurd", "abuse", "access", "accident"
-    , "account", "accuse", "achieve", "acid", "acoustic", "acquire"
-    , "across", "act", "action", "actor", "actress", "actual"
-    , "adapt", "add", "addict", "address", "adjust", "admit"
-    , "adult", "advance", "advice", "aerobic", "affair", "afford"
-    , "afraid", "again", "age", "agent", "agree", "ahead"
-    , "aim", "air", "airport", "aisle", "alarm", "album"
-    , "alcohol", "alert", "alien", "all", "alley", "allow"
-    , "almost", "alone", "alpha", "already", "also", "alter"
-    , "always", "amateur", "amazing", "among", "amount", "amused"
-    , "analyst", "anchor", "ancient", "anger", "angle", "angry"
-    , "animal", "ankle", "announce", "annual", "another", "answer"
-    , "antenna", "antique", "anxiety", "any", "apart", "apology"
-    , "appear", "apple", "approve", "april", "arch", "arctic"
-    , "area", "arena", "argue", "arm", "armed", "armor"
-    , "army", "around", "arrange", "arrest", "arrive", "arrow"
-    , "art", "artefact", "artist", "artwork", "ask", "aspect"
-    , "assault", "asset", "assist", "assume", "asthma", "athlete"
-    , "atom", "attack", "attend", "attitude", "attract", "auction"
-    , "audit", "august", "aunt", "author", "auto", "autumn"
-    , "average", "avocado", "avoid", "awake", "aware", "away"
-    , "awesome", "awful", "awkward", "axis", "baby", "bachelor"
-    , "bacon", "badge", "bag", "balance", "balcony", "ball"
-    , "bamboo", "banana", "banner", "bar", "barely", "bargain"
-    , "barrel", "base", "basic", "basket", "battle", "beach"
-    , "bean", "beauty", "because", "become", "beef", "before"
-    , "begin", "behave", "behind", "believe", "below", "belt"
-    , "bench", "benefit", "best", "betray", "better", "between"
-    , "beyond", "bicycle", "bid", "bike", "bind", "biology"
-    , "bird", "birth", "bitter", "black", "blade", "blame"
-    , "blanket", "blast", "bleak", "bless", "blind", "blood"
-    , "blossom", "blouse", "blue", "blur", "blush", "board"
-    , "boat", "body", "boil", "bomb", "bone", "bonus"
-    , "book", "boost", "border", "boring", "borrow", "boss"
-    , "bottom", "bounce", "box", "boy", "bracket", "brain"
-    , "brand", "brass", "brave", "bread", "breeze", "brick"
-    , "bridge", "brief", "bright", "bring", "brisk", "broccoli"
-    , "broken", "bronze", "broom", "brother", "brown", "brush"
-    , "bubble", "buddy", "budget", "buffalo", "build", "bulb"
-    , "bulk", "bullet", "bundle", "bunker", "burden", "burger"
-    , "burst", "bus", "business", "busy", "butter", "buyer"
-    , "buzz", "cabbage", "cabin", "cable", "cactus", "cage"
-    , "cake", "call", "calm", "camera", "camp", "can"
-    , "canal", "cancel", "candy", "cannon", "canoe", "canvas"
-    , "canyon", "capable", "capital", "captain", "car", "carbon"
-    , "card", "cargo", "carpet", "carry", "cart", "case"
-    , "cash", "casino", "castle", "casual", "cat", "catalog"
-    , "catch", "category", "cattle", "caught", "cause", "caution"
-    , "cave", "ceiling", "celery", "cement", "census", "century"
-    , "cereal", "certain", "chair", "chalk", "champion", "change"
-    , "chaos", "chapter", "charge", "chase", "chat", "cheap"
-    , "check", "cheese", "chef", "cherry", "chest", "chicken"
-    , "chief", "child", "chimney", "choice", "choose", "chronic"
-    , "chuckle", "chunk", "churn", "cigar", "cinnamon", "circle"
-    , "citizen", "city", "civil", "claim", "clap", "clarify"
-    , "claw", "clay", "clean", "clerk", "clever", "click"
-    , "client", "cliff", "climb", "clinic", "clip", "clock"
-    , "clog", "close", "cloth", "cloud", "clown", "club"
-    , "clump", "cluster", "clutch", "coach", "coast", "coconut"
-    , "code", "coffee", "coil", "coin", "collect", "color"
-    , "column", "combine", "come", "comfort", "comic", "common"
-    , "company", "concert", "conduct", "confirm", "congress", "connect"
-    , "consider", "control", "convince", "cook", "cool", "copper"
-    , "copy", "coral", "core", "corn", "correct", "cost"
-    , "cotton", "couch", "country", "couple", "course", "cousin"
-    , "cover", "coyote", "crack", "cradle", "craft", "cram"
-    , "crane", "crash", "crater", "crawl", "crazy", "cream"
-    , "credit", "creek", "crew", "cricket", "crime", "crisp"
-    , "critic", "crop", "cross", "crouch", "crowd", "crucial"
-    , "cruel", "cruise", "crumble", "crunch", "crush", "cry"
-    , "crystal", "cube", "culture", "cup", "cupboard", "curious"
-    , "current", "curtain", "curve", "cushion", "custom", "cute"
-    , "cycle", "dad", "damage", "damp", "dance", "danger"
-    , "daring", "dash", "daughter", "dawn", "day", "deal"
-    , "debate", "debris", "decade", "december", "decide", "decline"
-    , "decorate", "decrease", "deer", "defense", "define", "defy"
-    , "degree", "delay", "deliver", "demand", "demise", "denial"
-    , "dentist", "deny", "depart", "depend", "deposit", "depth"
-    , "deputy", "derive", "describe", "desert", "design", "desk"
-    , "despair", "destroy", "detail", "detect", "develop", "device"
-    , "devote", "diagram", "dial", "diamond", "diary", "dice"
-    , "diesel", "diet", "differ", "digital", "dignity", "dilemma"
-    , "dinner", "dinosaur", "direct", "dirt", "disagree", "discover"
-    , "disease", "dish", "dismiss", "disorder", "display", "distance"
-    , "divert", "divide", "divorce", "dizzy", "doctor", "document"
-    , "dog", "doll", "dolphin", "domain", "donate", "donkey"
-    , "donor", "door", "dose", "double", "dove", "draft"
-    , "dragon", "drama", "drastic", "draw", "dream", "dress"
-    , "drift", "drill", "drink", "drip", "drive", "drop"
-    , "drum", "dry", "duck", "dumb", "dune", "during"
-    , "dust", "dutch", "duty", "dwarf", "dynamic", "eager"
-    , "eagle", "early", "earn", "earth", "easily", "east"
-    , "easy", "echo", "ecology", "economy", "edge", "edit"
-    , "educate", "effort", "egg", "eight", "either", "elbow"
-    , "elder", "electric", "elegant", "element", "elephant", "elevator"
-    , "elite", "else", "embark", "embody", "embrace", "emerge"
-    , "emotion", "employ", "empower", "empty", "enable", "enact"
-    , "end", "endless", "endorse", "enemy", "energy", "enforce"
-    , "engage", "engine", "enhance", "enjoy", "enlist", "enough"
-    , "enrich", "enroll", "ensure", "enter", "entire", "entry"
-    , "envelope", "episode", "equal", "equip", "era", "erase"
-    , "erode", "erosion", "error", "erupt", "escape", "essay"
-    , "essence", "estate", "eternal", "ethics", "evidence", "evil"
-    , "evoke", "evolve", "exact", "example", "excess", "exchange"
-    , "excite", "exclude", "excuse", "execute", "exercise", "exhaust"
-    , "exhibit", "exile", "exist", "exit", "exotic", "expand"
-    , "expect", "expire", "explain", "expose", "express", "extend"
-    , "extra", "eye", "eyebrow", "fabric", "face", "faculty"
-    , "fade", "faint", "faith", "fall", "false", "fame"
-    , "family", "famous", "fan", "fancy", "fantasy", "farm"
-    , "fashion", "fat", "fatal", "father", "fatigue", "fault"
-    , "favorite", "feature", "february", "federal", "fee", "feed"
-    , "feel", "female", "fence", "festival", "fetch", "fever"
-    , "few", "fiber", "fiction", "field", "figure", "file"
-    , "film", "filter", "final", "find", "fine", "finger"
-    , "finish", "fire", "firm", "first", "fiscal", "fish"
-    , "fit", "fitness", "fix", "flag", "flame", "flash"
-    , "flat", "flavor", "flee", "flight", "flip", "float"
-    , "flock", "floor", "flower", "fluid", "flush", "fly"
-    , "foam", "focus", "fog", "foil", "fold", "follow"
-    , "food", "foot", "force", "forest", "forget", "fork"
-    , "fortune", "forum", "forward", "fossil", "foster", "found"
-    , "fox", "fragile", "frame", "frequent", "fresh", "friend"
-    , "fringe", "frog", "front", "frost", "frown", "frozen"
-    , "fruit", "fuel", "fun", "funny", "furnace", "fury"
-    , "future", "gadget", "gain", "galaxy", "gallery", "game"
-    , "gap", "garage", "garbage", "garden", "garlic", "garment"
-    , "gas", "gasp", "gate", "gather", "gauge", "gaze"
-    , "general", "genius", "genre", "gentle", "genuine", "gesture"
-    , "ghost", "giant", "gift", "giggle", "ginger", "giraffe"
-    , "girl", "give", "glad", "glance", "glare", "glass"
-    , "glide", "glimpse", "globe", "gloom", "glory", "glove"
-    , "glow", "glue", "goat", "goddess", "gold", "good"
-    , "goose", "gorilla", "gospel", "gossip", "govern", "gown"
-    , "grab", "grace", "grain", "grant", "grape", "grass"
-    , "gravity", "great", "green", "grid", "grief", "grit"
-    , "grocery", "group", "grow", "grunt", "guard", "guess"
-    , "guide", "guilt", "guitar", "gun", "gym", "habit"
-    , "hair", "half", "hammer", "hamster", "hand", "happy"
-    , "harbor", "hard", "harsh", "harvest", "hat", "have"
-    , "hawk", "hazard", "head", "health", "heart", "heavy"
-    , "hedgehog", "height", "hello", "helmet", "help", "hen"
-    , "hero", "hidden", "high", "hill", "hint", "hip"
-    , "hire", "history", "hobby", "hockey", "hold", "hole"
-    , "holiday", "hollow", "home", "honey", "hood", "hope"
-    , "horn", "horror", "horse", "hospital", "host", "hotel"
-    , "hour", "hover", "hub", "huge", "human", "humble"
-    , "humor", "hundred", "hungry", "hunt", "hurdle", "hurry"
-    , "hurt", "husband", "hybrid", "ice", "icon", "idea"
-    , "identify", "idle", "ignore", "ill", "illegal", "illness"
-    , "image", "imitate", "immense", "immune", "impact", "impose"
-    , "improve", "impulse", "inch", "include", "income", "increase"
-    , "index", "indicate", "indoor", "industry", "infant", "inflict"
-    , "inform", "inhale", "inherit", "initial", "inject", "injury"
-    , "inmate", "inner", "innocent", "input", "inquiry", "insane"
-    , "insect", "inside", "inspire", "install", "intact", "interest"
-    , "into", "invest", "invite", "involve", "iron", "island"
-    , "isolate", "issue", "item", "ivory", "jacket", "jaguar"
-    , "jar", "jazz", "jealous", "jeans", "jelly", "jewel"
-    , "job", "join", "joke", "journey", "joy", "judge"
-    , "juice", "jump", "jungle", "junior", "junk", "just"
-    , "kangaroo", "keen", "keep", "ketchup", "key", "kick"
-    , "kid", "kidney", "kind", "kingdom", "kiss", "kit"
-    , "kitchen", "kite", "kitten", "kiwi", "knee", "knife"
-    , "knock", "know", "lab", "label", "labor", "ladder"
-    , "lady", "lake", "lamp", "language", "laptop", "large"
-    , "later", "latin", "laugh", "laundry", "lava", "law"
-    , "lawn", "lawsuit", "layer", "lazy", "leader", "leaf"
-    , "learn", "leave", "lecture", "left", "leg", "legal"
-    , "legend", "leisure", "lemon", "lend", "length", "lens"
-    , "leopard", "lesson", "letter", "level", "liar", "liberty"
-    , "library", "license", "life", "lift", "light", "like"
-    , "limb", "limit", "link", "lion", "liquid", "list"
-    , "little", "live", "lizard", "load", "loan", "lobster"
-    , "local", "lock", "logic", "lonely", "long", "loop"
-    , "lottery", "loud", "lounge", "love", "loyal", "lucky"
-    , "luggage", "lumber", "lunar", "lunch", "luxury", "lyrics"
-    , "machine", "mad", "magic", "magnet", "maid", "mail"
-    , "main", "major", "make", "mammal", "man", "manage"
-    , "mandate", "mango", "mansion", "manual", "maple", "marble"
-    , "march", "margin", "marine", "market", "marriage", "mask"
-    , "mass", "master", "match", "material", "math", "matrix"
-    , "matter", "maximum", "maze", "meadow", "mean", "measure"
-    , "meat", "mechanic", "medal", "media", "melody", "melt"
-    , "member", "memory", "mention", "menu", "mercy", "merge"
-    , "merit", "merry", "mesh", "message", "metal", "method"
-    , "middle", "midnight", "milk", "million", "mimic", "mind"
-    , "minimum", "minor", "minute", "miracle", "mirror", "misery"
-    , "miss", "mistake", "mix", "mixed", "mixture", "mobile"
-    , "model", "modify", "mom", "moment", "monitor", "monkey"
-    , "monster", "month", "moon", "moral", "more", "morning"
-    , "mosquito", "mother", "motion", "motor", "mountain", "mouse"
-    , "move", "movie", "much", "muffin", "mule", "multiply"
-    , "muscle", "museum", "mushroom", "music", "must", "mutual"
-    , "myself", "mystery", "myth", "naive", "name", "napkin"
-    , "narrow", "nasty", "nation", "nature", "near", "neck"
-    , "need", "negative", "neglect", "neither", "nephew", "nerve"
-    , "nest", "net", "network", "neutral", "never", "news"
-    , "next", "nice", "night", "noble", "noise", "nominee"
-    , "noodle", "normal", "north", "nose", "notable", "note"
-    , "nothing", "notice", "novel", "now", "nuclear", "number"
-    , "nurse", "nut", "oak", "obey", "object", "oblige"
-    , "obscure", "observe", "obtain", "obvious", "occur", "ocean"
-    , "october", "odor", "off", "offer", "office", "often"
-    , "oil", "okay", "old", "olive", "olympic", "omit"
-    , "once", "one", "onion", "online", "only", "open"
-    , "opera", "opinion", "oppose", "option", "orange", "orbit"
-    , "orchard", "order", "ordinary", "organ", "orient", "original"
-    , "orphan", "ostrich", "other", "outdoor", "outer", "output"
-    , "outside", "oval", "oven", "over", "own", "owner"
-    , "oxygen", "oyster", "ozone", "pact", "paddle", "page"
-    , "pair", "palace", "palm", "panda", "panel", "panic"
-    , "panther", "paper", "parade", "parent", "park", "parrot"
-    , "party", "pass", "patch", "path", "patient", "patrol"
-    , "pattern", "pause", "pave", "payment", "peace", "peanut"
-    , "pear", "peasant", "pelican", "pen", "penalty", "pencil"
-    , "people", "pepper", "perfect", "permit", "person", "pet"
-    , "phone", "photo", "phrase", "physical", "piano", "picnic"
-    , "picture", "piece", "pig", "pigeon", "pill", "pilot"
-    , "pink", "pioneer", "pipe", "pistol", "pitch", "pizza"
-    , "place", "planet", "plastic", "plate", "play", "please"
-    , "pledge", "pluck", "plug", "plunge", "poem", "poet"
-    , "point", "polar", "pole", "police", "pond", "pony"
-    , "pool", "popular", "portion", "position", "possible", "post"
-    , "potato", "pottery", "poverty", "powder", "power", "practice"
-    , "praise", "predict", "prefer", "prepare", "present", "pretty"
-    , "prevent", "price", "pride", "primary", "print", "priority"
-    , "prison", "private", "prize", "problem", "process", "produce"
-    , "profit", "program", "project", "promote", "proof", "property"
-    , "prosper", "protect", "proud", "provide", "public", "pudding"
-    , "pull", "pulp", "pulse", "pumpkin", "punch", "pupil"
-    , "puppy", "purchase", "purity", "purpose", "purse", "push"
-    , "put", "puzzle", "pyramid", "quality", "quantum", "quarter"
-    , "question", "quick", "quit", "quiz", "quote", "rabbit"
-    , "raccoon", "race", "rack", "radar", "radio", "rail"
-    , "rain", "raise", "rally", "ramp", "ranch", "random"
-    , "range", "rapid", "rare", "rate", "rather", "raven"
-    , "raw", "razor", "ready", "real", "reason", "rebel"
-    , "rebuild", "recall", "receive", "recipe", "record", "recycle"
-    , "reduce", "reflect", "reform", "refuse", "region", "regret"
-    , "regular", "reject", "relax", "release", "relief", "rely"
-    , "remain", "remember", "remind", "remove", "render", "renew"
-    , "rent", "reopen", "repair", "repeat", "replace", "report"
-    , "require", "rescue", "resemble", "resist", "resource", "response"
-    , "result", "retire", "retreat", "return", "reunion", "reveal"
-    , "review", "reward", "rhythm", "rib", "ribbon", "rice"
-    , "rich", "ride", "ridge", "rifle", "right", "rigid"
-    , "ring", "riot", "ripple", "risk", "ritual", "rival"
-    , "river", "road", "roast", "robot", "robust", "rocket"
-    , "romance", "roof", "rookie", "room", "rose", "rotate"
-    , "rough", "round", "route", "royal", "rubber", "rude"
-    , "rug", "rule", "run", "runway", "rural", "sad"
-    , "saddle", "sadness", "safe", "sail", "salad", "salmon"
-    , "salon", "salt", "salute", "same", "sample", "sand"
-    , "satisfy", "satoshi", "sauce", "sausage", "save", "say"
-    , "scale", "scan", "scare", "scatter", "scene", "scheme"
-    , "school", "science", "scissors", "scorpion", "scout", "scrap"
-    , "screen", "script", "scrub", "sea", "search", "season"
-    , "seat", "second", "secret", "section", "security", "seed"
-    , "seek", "segment", "select", "sell", "seminar", "senior"
-    , "sense", "sentence", "series", "service", "session", "settle"
-    , "setup", "seven", "shadow", "shaft", "shallow", "share"
-    , "shed", "shell", "sheriff", "shield", "shift", "shine"
-    , "ship", "shiver", "shock", "shoe", "shoot", "shop"
-    , "short", "shoulder", "shove", "shrimp", "shrug", "shuffle"
-    , "shy", "sibling", "sick", "side", "siege", "sight"
-    , "sign", "silent", "silk", "silly", "silver", "similar"
-    , "simple", "since", "sing", "siren", "sister", "situate"
-    , "six", "size", "skate", "sketch", "ski", "skill"
-    , "skin", "skirt", "skull", "slab", "slam", "sleep"
-    , "slender", "slice", "slide", "slight", "slim", "slogan"
-    , "slot", "slow", "slush", "small", "smart", "smile"
-    , "smoke", "smooth", "snack", "snake", "snap", "sniff"
-    , "snow", "soap", "soccer", "social", "sock", "soda"
-    , "soft", "solar", "soldier", "solid", "solution", "solve"
-    , "someone", "song", "soon", "sorry", "sort", "soul"
-    , "sound", "soup", "source", "south", "space", "spare"
-    , "spatial", "spawn", "speak", "special", "speed", "spell"
-    , "spend", "sphere", "spice", "spider", "spike", "spin"
-    , "spirit", "split", "spoil", "sponsor", "spoon", "sport"
-    , "spot", "spray", "spread", "spring", "spy", "square"
-    , "squeeze", "squirrel", "stable", "stadium", "staff", "stage"
-    , "stairs", "stamp", "stand", "start", "state", "stay"
-    , "steak", "steel", "stem", "step", "stereo", "stick"
-    , "still", "sting", "stock", "stomach", "stone", "stool"
-    , "story", "stove", "strategy", "street", "strike", "strong"
-    , "struggle", "student", "stuff", "stumble", "style", "subject"
-    , "submit", "subway", "success", "such", "sudden", "suffer"
-    , "sugar", "suggest", "suit", "summer", "sun", "sunny"
-    , "sunset", "super", "supply", "supreme", "sure", "surface"
-    , "surge", "surprise", "surround", "survey", "suspect", "sustain"
-    , "swallow", "swamp", "swap", "swarm", "swear", "sweet"
-    , "swift", "swim", "swing", "switch", "sword", "symbol"
-    , "symptom", "syrup", "system", "table", "tackle", "tag"
-    , "tail", "talent", "talk", "tank", "tape", "target"
-    , "task", "taste", "tattoo", "taxi", "teach", "team"
-    , "tell", "ten", "tenant", "tennis", "tent", "term"
-    , "test", "text", "thank", "that", "theme", "then"
-    , "theory", "there", "they", "thing", "this", "thought"
-    , "three", "thrive", "throw", "thumb", "thunder", "ticket"
-    , "tide", "tiger", "tilt", "timber", "time", "tiny"
-    , "tip", "tired", "tissue", "title", "toast", "tobacco"
-    , "today", "toddler", "toe", "together", "toilet", "token"
-    , "tomato", "tomorrow", "tone", "tongue", "tonight", "tool"
-    , "tooth", "top", "topic", "topple", "torch", "tornado"
-    , "tortoise", "toss", "total", "tourist", "toward", "tower"
-    , "town", "toy", "track", "trade", "traffic", "tragic"
-    , "train", "transfer", "trap", "trash", "travel", "tray"
-    , "treat", "tree", "trend", "trial", "tribe", "trick"
-    , "trigger", "trim", "trip", "trophy", "trouble", "truck"
-    , "true", "truly", "trumpet", "trust", "truth", "try"
-    , "tube", "tuition", "tumble", "tuna", "tunnel", "turkey"
-    , "turn", "turtle", "twelve", "twenty", "twice", "twin"
-    , "twist", "two", "type", "typical", "ugly", "umbrella"
-    , "unable", "unaware", "uncle", "uncover", "under", "undo"
-    , "unfair", "unfold", "unhappy", "uniform", "unique", "unit"
-    , "universe", "unknown", "unlock", "until", "unusual", "unveil"
-    , "update", "upgrade", "uphold", "upon", "upper", "upset"
-    , "urban", "urge", "usage", "use", "used", "useful"
-    , "useless", "usual", "utility", "vacant", "vacuum", "vague"
-    , "valid", "valley", "valve", "van", "vanish", "vapor"
-    , "various", "vast", "vault", "vehicle", "velvet", "vendor"
-    , "venture", "venue", "verb", "verify", "version", "very"
-    , "vessel", "veteran", "viable", "vibrant", "vicious", "victory"
-    , "video", "view", "village", "vintage", "violin", "virtual"
-    , "virus", "visa", "visit", "visual", "vital", "vivid"
-    , "vocal", "voice", "void", "volcano", "volume", "vote"
-    , "voyage", "wage", "wagon", "wait", "walk", "wall"
-    , "walnut", "want", "warfare", "warm", "warrior", "wash"
-    , "wasp", "waste", "water", "wave", "way", "wealth"
-    , "weapon", "wear", "weasel", "weather", "web", "wedding"
-    , "weekend", "weird", "welcome", "west", "wet", "whale"
-    , "what", "wheat", "wheel", "when", "where", "whip"
-    , "whisper", "wide", "width", "wife", "wild", "will"
-    , "win", "window", "wine", "wing", "wink", "winner"
-    , "winter", "wire", "wisdom", "wise", "wish", "witness"
-    , "wolf", "woman", "wonder", "wood", "wool", "word"
-    , "work", "world", "worry", "worth", "wrap", "wreck"
-    , "wrestle", "wrist", "write", "wrong", "yard", "year"
-    , "yellow", "you", "young", "youth", "zebra", "zero"
-    , "zone", "zoo"
-    ]
diff --git a/Network/Haskoin/Internals.hs b/Network/Haskoin/Internals.hs
deleted file mode 100644
--- a/Network/Haskoin/Internals.hs
+++ /dev/null
@@ -1,60 +0,0 @@
-{-|
-  This module expose haskoin internals. No guarantee is made on the
-  stability of the interface of these internal modules.
--}
-module Network.Haskoin.Internals
-( module Network.Haskoin.Util
-, module Network.Haskoin.Constants
-, module Network.Haskoin.Crypto.Hash
-, module Network.Haskoin.Crypto.Base58
-, module Network.Haskoin.Crypto.Keys
-, module Network.Haskoin.Crypto.ExtendedKeys
-, module Network.Haskoin.Crypto.ECDSA
-, module Network.Haskoin.Crypto.Mnemonic
-, module Network.Haskoin.Node.Types
-, module Network.Haskoin.Node.Message
-, module Network.Haskoin.Node.Bloom
-, module Network.Haskoin.Script.Types
-, module Network.Haskoin.Script.Parser
-, module Network.Haskoin.Script.SigHash
-, module Network.Haskoin.Script.Evaluator
-, module Network.Haskoin.Transaction.Types
-, module Network.Haskoin.Transaction.Builder
-, module Network.Haskoin.Block.Types
-, module Network.Haskoin.Block.Merkle
-, module Network.Haskoin.Test.Util
-, module Network.Haskoin.Test.Crypto
-, module Network.Haskoin.Test.Node
-, module Network.Haskoin.Test.Message
-, module Network.Haskoin.Test.Script
-, module Network.Haskoin.Test.Transaction
-, module Network.Haskoin.Test.Block
-) where
-
-import Network.Haskoin.Util
-import Network.Haskoin.Constants
-import Network.Haskoin.Crypto.Hash
-import Network.Haskoin.Crypto.Base58
-import Network.Haskoin.Crypto.Keys
-import Network.Haskoin.Crypto.ExtendedKeys
-import Network.Haskoin.Crypto.ECDSA
-import Network.Haskoin.Crypto.Mnemonic
-import Network.Haskoin.Node.Types
-import Network.Haskoin.Node.Message
-import Network.Haskoin.Node.Bloom
-import Network.Haskoin.Script.Types
-import Network.Haskoin.Script.Parser
-import Network.Haskoin.Script.SigHash
-import Network.Haskoin.Script.Evaluator
-import Network.Haskoin.Transaction.Types
-import Network.Haskoin.Transaction.Builder
-import Network.Haskoin.Block.Types
-import Network.Haskoin.Block.Merkle
-import Network.Haskoin.Test.Util
-import Network.Haskoin.Test.Crypto
-import Network.Haskoin.Test.Node
-import Network.Haskoin.Test.Message
-import Network.Haskoin.Test.Script
-import Network.Haskoin.Test.Transaction
-import Network.Haskoin.Test.Block
-
diff --git a/Network/Haskoin/Node.hs b/Network/Haskoin/Node.hs
deleted file mode 100644
--- a/Network/Haskoin/Node.hs
+++ /dev/null
@@ -1,52 +0,0 @@
-{-|
-  This package provides basic types used for the Bitcoin networking protocol
-  together with Data.Serialize instances for efficiently serializing and
-  de-serializing them. More information on the bitcoin protocol is available
-  here: <http://en.bitcoin.it/wiki/Protocol_specification>
--}
-module Network.Haskoin.Node
-(
-  -- * Requesting data
-  GetData(..)
-, Inv(..)
-, InvVector(..)
-, InvType(..)
-, NotFound(..)
-
-  -- * Network types
-, VarInt(..)
-, VarString(..)
-, NetworkAddress(..)
-, Addr(..)
-, NetworkAddressTime
-, Version(..)
-, Ping(..)
-, Pong(..)
-, Alert(..)
-, Reject(..)
-, RejectCode(..)
-, reject
-
-  -- * Messages
-, Message(..)
-, MessageHeader(..)
-, MessageCommand(..)
-
-  -- * Bloom filters
-, BloomFlags(..)
-, BloomFilter(..)
-, FilterLoad(..)
-, FilterAdd(..)
-, bloomCreate
-, bloomInsert
-, bloomContains
-, isBloomValid
-, isBloomEmpty
-, isBloomFull
-
-) where
-
-import Network.Haskoin.Node.Message
-import Network.Haskoin.Node.Types
-import Network.Haskoin.Node.Bloom
-
diff --git a/Network/Haskoin/Node/Bloom.hs b/Network/Haskoin/Node/Bloom.hs
deleted file mode 100644
--- a/Network/Haskoin/Node/Bloom.hs
+++ /dev/null
@@ -1,222 +0,0 @@
-module Network.Haskoin.Node.Bloom
-( BloomFlags(..)
-, BloomFilter(..)
-, FilterLoad(..)
-, FilterAdd(..)
-, bloomCreate
-, bloomInsert
-, bloomContains
-, isBloomValid
-, isBloomEmpty
-, isBloomFull
-) where
-
-import Control.Monad (replicateM, forM_)
-import Control.DeepSeq (NFData, rnf)
-
-import Data.Word
-import Data.Bits
-import Data.Hash.Murmur (murmur3)
-import Data.Serialize (Serialize, get, put)
-import Data.Serialize.Get
-    ( getWord8
-    , getWord32le
-    , getByteString
-    )
-import Data.Serialize.Put
-    ( putWord8
-    , putWord32le
-    , putByteString
-    )
-import qualified Data.Foldable as F
-import qualified Data.Sequence as S
-import qualified Data.ByteString as BS
-
-import Network.Haskoin.Node.Types
-
--- 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001%
-maxBloomSize :: Int
-maxBloomSize = 36000
-
-maxHashFuncs :: Word32
-maxHashFuncs = 50
-
-ln2Squared :: Double
-ln2Squared = 0.4804530139182014246671025263266649717305529515945455
-
-ln2 :: Double
-ln2 = 0.6931471805599453094172321214581765680755001343602552
-
-bitMask :: [Word8]
-bitMask = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80]
-
--- | The bloom flags are used to tell the remote peer how to auto-update
--- the provided bloom filter.
-data BloomFlags
-    = BloomUpdateNone         -- ^ Never update
-    | BloomUpdateAll          -- ^ Auto-update on all outputs
-    | BloomUpdateP2PubKeyOnly
-    -- ^ Only auto-update on outputs that are pay-to-pubkey or pay-to-multisig.
-    -- This is the default setting.
-    deriving (Eq, Show, Read)
-
-instance NFData BloomFlags where rnf x = seq x ()
-
-instance Serialize BloomFlags where
-    get = go =<< getWord8
-      where
-        go 0 = return BloomUpdateNone
-        go 1 = return BloomUpdateAll
-        go 2 = return BloomUpdateP2PubKeyOnly
-        go _ = fail "BloomFlags get: Invalid bloom flag"
-
-    put f = putWord8 $ case f of
-        BloomUpdateNone         -> 0
-        BloomUpdateAll          -> 1
-        BloomUpdateP2PubKeyOnly -> 2
-
--- | A bloom filter is a probabilistic data structure that SPV clients send to
--- other peers to filter the set of transactions received from them. Bloom
--- filters are probabilistic and have a false positive rate. Some transactions
--- that pass the filter may not be relevant to the receiving peer. By
--- controlling the false positive rate, SPV nodes can trade off bandwidth
--- versus privacy.
-data BloomFilter = BloomFilter
-    { bloomData      :: !(S.Seq Word8)
-    -- ^ Bloom filter data
-    , bloomHashFuncs :: !Word32
-    -- ^ Number of hash functions for this filter
-    , bloomTweak     :: !Word32
-    -- ^ Hash function random nonce
-    , bloomFlags     :: !BloomFlags
-    -- ^ Bloom filter auto-update flags
-    }
-    deriving (Eq, Show, Read)
-
-instance NFData BloomFilter where
-    rnf (BloomFilter d h t g) =
-        rnf d `seq` rnf h `seq` rnf t `seq` rnf g
-
-instance Serialize BloomFilter where
-
-    get = BloomFilter <$> (S.fromList <$> (readDat =<< get))
-                      <*> getWord32le <*> getWord32le
-                      <*> get
-      where
-        readDat (VarInt len) = replicateM (fromIntegral len) getWord8
-
-    put (BloomFilter dat hashFuncs tweak flags) = do
-        put $ VarInt $ fromIntegral $ S.length dat
-        forM_ (F.toList dat) putWord8
-        putWord32le hashFuncs
-        putWord32le tweak
-        put flags
-
--- | Set a new bloom filter on the peer connection.
-newtype FilterLoad = FilterLoad { filterLoadBloomFilter :: BloomFilter }
-    deriving (Eq, Show, Read)
-
-instance NFData FilterLoad where
-    rnf (FilterLoad f) = rnf f
-
-instance Serialize FilterLoad where
-    get = FilterLoad <$> get
-    put (FilterLoad f) = put f
-
--- | Add the given data element to the connections current filter without
--- requiring a completely new one to be set.
-newtype FilterAdd = FilterAdd { getFilterData :: BS.ByteString }
-    deriving (Eq, Show, Read)
-
-instance NFData FilterAdd where
-    rnf (FilterAdd f) = rnf f
-
-instance Serialize FilterAdd where
-    get = do
-        (VarInt len) <- get
-        dat <- getByteString $ fromIntegral len
-        return $ FilterAdd dat
-
-    put (FilterAdd bs) = do
-        put $ VarInt $ fromIntegral $ BS.length bs
-        putByteString bs
-
-
--- | Build a bloom filter that will provide the given false positive rate when
--- the given number of elements have been inserted.
-bloomCreate :: Int          -- ^ Number of elements
-            -> Double       -- ^ False positive rate
-            -> Word32
-             -- ^ A random nonce (tweak) for the hash function. It should be
-             -- a random number but the secureness of the random value is not
-             -- of geat consequence.
-            -> BloomFlags   -- ^ Bloom filter flags
-            -> BloomFilter  -- ^ Bloom filter
-bloomCreate numElem fpRate =
-    BloomFilter (S.replicate bloomSize 0) numHashF
-  where
-    -- Bloom filter size in bytes
-    bloomSize = truncate $ (min a b) / 8
-    -- Suggested size in bits
-    a         = -1 / ln2Squared * (fromIntegral numElem) * log fpRate
-    -- Maximum size in bits
-    b         = fromIntegral $ maxBloomSize * 8
-    numHashF  = truncate $ min c (fromIntegral maxHashFuncs)
-    -- Suggested number of hash functions
-    c         = (fromIntegral bloomSize) * 8 / (fromIntegral numElem) * ln2
-
-bloomHash :: BloomFilter -> Word32 -> BS.ByteString -> Word32
-bloomHash bfilter hashNum bs =
-    murmur3 seed bs `mod` (fromIntegral (S.length (bloomData bfilter)) * 8)
-  where
-    seed = hashNum * 0xfba4c795 + (bloomTweak bfilter)
-
--- | Insert arbitrary data into a bloom filter. Returns the new bloom filter
--- containing the new data.
-bloomInsert :: BloomFilter    -- ^ Original bloom filter
-            -> BS.ByteString  -- ^ New data to insert
-            -> BloomFilter    -- ^ Bloom filter containing the new data
-bloomInsert bfilter bs
-    | isBloomFull bfilter = bfilter
-    | otherwise = bfilter { bloomData = newData }
-  where
-    idxs    = map (\i -> bloomHash bfilter i bs) [0..bloomHashFuncs bfilter - 1]
-    upd s i = S.adjust (.|. bitMask !! fromIntegral (7 .&. i))
-                       (fromIntegral $ i `shiftR` 3) s
-    newData = foldl upd (bloomData bfilter) idxs
-
--- | Tests if some arbitrary data matches the filter. This can be either because
--- the data was inserted into the filter or because it is a false positive.
-bloomContains :: BloomFilter    -- ^ Bloom filter
-              -> BS.ByteString
-              -- ^ Data that will be checked against the given bloom filter
-              -> Bool
-              -- ^ Returns True if the data matches the filter
-bloomContains bfilter bs
-    | isBloomFull bfilter  = True
-    | isBloomEmpty bfilter = False
-    | otherwise            = all isSet idxs
-  where
-    s       = bloomData bfilter
-    idxs    = map (\i -> bloomHash bfilter i bs) [0..bloomHashFuncs bfilter - 1]
-    isSet i = (S.index s (fromIntegral $ i `shiftR` 3))
-          .&. (bitMask !! fromIntegral (7 .&. i)) /= 0
-
--- TODO: Write bloomRelevantUpdate
--- bloomRelevantUpdate :: BloomFilter -> Tx -> Hash256 -> Maybe BloomFilter
-
--- | Returns True if the filter is empty (all bytes set to 0x00)
-isBloomEmpty :: BloomFilter -> Bool
-isBloomEmpty bfilter = all (== 0x00) $ F.toList $ bloomData bfilter
-
--- | Returns True if the filter is full (all bytes set to 0xff)
-isBloomFull :: BloomFilter -> Bool
-isBloomFull bfilter = all (== 0xff) $ F.toList $ bloomData bfilter
-
--- | Tests if a given bloom filter is valid.
-isBloomValid :: BloomFilter -- ^ Bloom filter to test
-             -> Bool        -- ^ True if the given filter is valid
-isBloomValid bfilter =
-    (S.length $ bloomData bfilter) <= maxBloomSize &&
-    (bloomHashFuncs bfilter) <= maxHashFuncs
-
diff --git a/Network/Haskoin/Node/Message.hs b/Network/Haskoin/Node/Message.hs
deleted file mode 100644
--- a/Network/Haskoin/Node/Message.hs
+++ /dev/null
@@ -1,150 +0,0 @@
-module Network.Haskoin.Node.Message
-( Message(..)
-, MessageHeader(..)
-) where
-
-import           Control.DeepSeq                   (NFData, rnf)
-import           Control.Monad                     (unless)
-import qualified Data.ByteString                   as BS (append, empty, length)
-import           Data.Serialize                    (Serialize, encode, get, put)
-import           Data.Serialize.Get                (getByteString, getWord32be,
-                                                    getWord32le, isolate,
-                                                    lookAhead)
-import           Data.Serialize.Put                (putByteString, putWord32be,
-                                                    putWord32le)
-import           Data.Word                         (Word32)
-import           Network.Haskoin.Block.Merkle
-import           Network.Haskoin.Block.Types
-import           Network.Haskoin.Constants
-import           Network.Haskoin.Crypto.Hash
-import           Network.Haskoin.Node.Bloom
-import           Network.Haskoin.Node.Types
-import           Network.Haskoin.Transaction.Types
-
--- | Data type representing the header of a 'Message'. All messages sent between
--- nodes contain a message header.
-data MessageHeader =
-    MessageHeader {
-                  -- | Network magic bytes. It is used to differentiate
-                  -- messages meant for different bitcoin networks, such as
-                  -- prodnet and testnet.
-                    headMagic       :: !Word32
-                  -- | Message command identifying the type of message.
-                  -- included in the payload.
-                  , headCmd         :: !MessageCommand
-                  -- | Byte length of the payload.
-                  , headPayloadSize :: !Word32
-                  -- | Checksum of the payload.
-                  , headChecksum    :: !CheckSum32
-                  } deriving (Eq, Show, Read)
-
-instance NFData MessageHeader where
-    rnf (MessageHeader m c p s) = rnf m `seq` rnf c `seq` rnf p `seq` rnf s
-
-instance Serialize MessageHeader where
-
-    get = MessageHeader <$> getWord32be
-                        <*> get
-                        <*> getWord32le
-                        <*> get
-
-    put (MessageHeader m c l chk) = do
-        putWord32be m
-        put         c
-        putWord32le l
-        put         chk
-
--- | The 'Message' type is used to identify all the valid messages that can be
--- sent between bitcoin peers. Only values of type 'Message' will be accepted
--- by other bitcoin peers as bitcoin protocol messages need to be correctly
--- serialized with message headers. Serializing a 'Message' value will
--- include the 'MessageHeader' with the correct checksum value automatically.
--- No need to add the 'MessageHeader' separately.
-data Message
-    = MVersion !Version
-    | MVerAck
-    | MAddr !Addr
-    | MInv !Inv
-    | MGetData !GetData
-    | MNotFound !NotFound
-    | MGetBlocks !GetBlocks
-    | MGetHeaders !GetHeaders
-    | MTx !Tx
-    | MBlock !Block
-    | MMerkleBlock !MerkleBlock
-    | MHeaders !Headers
-    | MGetAddr
-    | MFilterLoad !FilterLoad
-    | MFilterAdd !FilterAdd
-    | MFilterClear
-    | MPing !Ping
-    | MPong !Pong
-    | MAlert !Alert
-    | MMempool
-    | MReject !Reject
-    deriving (Eq, Show)
-
-instance Serialize Message where
-
-    get = do
-        (MessageHeader mgc cmd len chk) <- get
-        bs <- lookAhead $ getByteString $ fromIntegral len
-        unless (mgc == networkMagic)
-            (fail $ "get: Invalid network magic bytes: " ++ (show mgc))
-        unless (checkSum32 bs == chk)
-            (fail $ "get: Invalid message checksum: " ++ (show chk))
-        if len > 0
-            then isolate (fromIntegral len) $ case cmd of
-                MCVersion     -> MVersion <$> get
-                MCAddr        -> MAddr <$> get
-                MCInv         -> MInv <$> get
-                MCGetData     -> MGetData <$> get
-                MCNotFound    -> MNotFound <$> get
-                MCGetBlocks   -> MGetBlocks <$> get
-                MCGetHeaders  -> MGetHeaders <$> get
-                MCTx          -> MTx <$> get
-                MCBlock       -> MBlock <$> get
-                MCMerkleBlock -> MMerkleBlock <$> get
-                MCHeaders     -> MHeaders <$> get
-                MCFilterLoad  -> MFilterLoad <$> get
-                MCFilterAdd   -> MFilterAdd <$> get
-                MCPing        -> MPing <$> get
-                MCPong        -> MPong <$> get
-                MCAlert       -> MAlert <$> get
-                MCReject      -> MReject <$> get
-                _             -> fail $ "get: Invalid command " ++ (show cmd)
-            else case cmd of
-                MCGetAddr     -> return MGetAddr
-                MCVerAck      -> return MVerAck
-                MCFilterClear -> return MFilterClear
-                MCMempool     -> return MMempool
-                _             -> fail $ "get: Invalid command " ++ (show cmd)
-
-    put msg = do
-        let (cmd, payload) = case msg of
-                MVersion m     -> (MCVersion, encode m)
-                MVerAck        -> (MCVerAck, BS.empty)
-                MAddr m        -> (MCAddr, encode m)
-                MInv m         -> (MCInv, encode m)
-                MGetData m     -> (MCGetData, encode m)
-                MNotFound m    -> (MCNotFound, encode m)
-                MGetBlocks m   -> (MCGetBlocks, encode m)
-                MGetHeaders m  -> (MCGetHeaders, encode m)
-                MTx m          -> (MCTx, encode m)
-                MBlock m       -> (MCBlock, encode m)
-                MMerkleBlock m -> (MCMerkleBlock, encode m)
-                MHeaders m     -> (MCHeaders, encode m)
-                MGetAddr       -> (MCGetAddr, BS.empty)
-                MFilterLoad m  -> (MCFilterLoad, encode m)
-                MFilterAdd m   -> (MCFilterAdd, encode m)
-                MFilterClear   -> (MCFilterClear, BS.empty)
-                MPing m        -> (MCPing, encode m)
-                MPong m        -> (MCPong, encode m)
-                MAlert m       -> (MCAlert, encode m)
-                MMempool       -> (MCMempool, BS.empty)
-                MReject m      -> (MCReject, encode m)
-            chk = checkSum32 payload
-            len = fromIntegral $ BS.length payload
-            header = MessageHeader networkMagic cmd len chk
-        putByteString $ (encode header) `BS.append` payload
-
diff --git a/Network/Haskoin/Node/Types.hs b/Network/Haskoin/Node/Types.hs
deleted file mode 100644
--- a/Network/Haskoin/Node/Types.hs
+++ /dev/null
@@ -1,599 +0,0 @@
-module Network.Haskoin.Node.Types
-( Addr(..)
-, NetworkAddressTime
-, Alert(..)
-, GetData(..)
-, Inv(..)
-, InvVector(..)
-, InvType(..)
-, NetworkAddress(..)
-, NotFound(..)
-, Ping(..)
-, Pong(..)
-, Reject(..)
-, RejectCode(..)
-, reject
-, VarInt(..)
-, VarString(..)
-, Version(..)
-, MessageCommand(..)
-) where
-
-import Control.DeepSeq (NFData, rnf)
-import Control.Monad (replicateM, liftM2, forM_, unless)
-
-import Data.Word (Word32, Word64)
-import Data.Serialize (Serialize, get, put)
-import Data.Serialize.Get
-    ( Get
-    , getWord8
-    , getWord16le
-    , getWord16be
-    , getWord32be
-    , getWord32host
-    , getWord32le
-    , getWord64le
-    , getByteString
-    , isEmpty
-    )
-import Data.Serialize.Put
-    ( Put
-    , putWord8
-    , putWord16le
-    , putWord16be
-    , putWord32be
-    , putWord32host
-    , putWord32le
-    , putWord64le
-    , putByteString
-    )
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as BS
-    ( length
-    , takeWhile
-    , empty
-    , null
-    , take
-    )
-import Data.ByteString.Char8 as C (replicate)
-import Data.String.Conversions (cs)
-import Network.Socket (SockAddr (SockAddrInet, SockAddrInet6))
-
-import Network.Haskoin.Crypto.Hash
-
--- | Network address with a timestamp
-type NetworkAddressTime = (Word32, NetworkAddress)
-
--- | Provides information on known nodes in the bitcoin network. An 'Addr'
--- type is sent inside a 'Message' as a response to a 'GetAddr' message.
-data Addr =
-    Addr {
-           -- List of addresses of other nodes on the network with timestamps.
-           addrList :: ![NetworkAddressTime]
-         }
-    deriving (Eq, Show)
-
-instance Serialize Addr where
-
-    get = Addr <$> (repList =<< get)
-      where
-        repList (VarInt c) = replicateM (fromIntegral c) action
-        action             = liftM2 (,) getWord32le get
-
-    put (Addr xs) = do
-        put $ VarInt $ fromIntegral $ length xs
-        forM_ xs $ \(a,b) -> putWord32le a >> put b
-
--- | Data type describing signed messages that can be sent between bitcoin
--- nodes to display important notifications to end users about the health of
--- the network.
-data Alert =
-    Alert {
-          -- | Alert payload.
-            alertPayload   :: !VarString
-          -- | ECDSA signature of the payload
-          , alertSignature :: !VarString
-          } deriving (Eq, Show, Read)
-
-instance NFData Alert where
-    rnf (Alert p s) = rnf p `seq` rnf s
-
-instance Serialize Alert where
-    get = Alert <$> get <*> get
-    put (Alert p s) = put p >> put s
-
--- | The 'GetData' type is used to retrieve information on a specific object
--- ('Block' or 'Tx') identified by the objects hash. The payload of a 'GetData'
--- request is a list of 'InvVector' which represent all the hashes for which a
--- node wants to request information. The response to a 'GetBlock' message
--- wille be either a 'Block' or a 'Tx' message depending on the type of the
--- object referenced by the hash. Usually, 'GetData' messages are sent after a
--- node receives an 'Inv' message to obtain information on unknown object
--- hashes.
-data GetData =
-    GetData {
-              -- | List of object hashes
-              getDataList :: ![InvVector]
-            } deriving (Eq, Show, Read)
-
-instance NFData GetData where
-    rnf (GetData l) = rnf l
-
-instance Serialize GetData where
-
-    get = GetData <$> (repList =<< get)
-      where
-        repList (VarInt c) = replicateM (fromIntegral c) get
-
-    put (GetData xs) = do
-        put $ VarInt $ fromIntegral $ length xs
-        forM_ xs put
-
--- | 'Inv' messages are used by nodes to advertise their knowledge of new
--- objects by publishing a list of hashes. 'Inv' messages can be sent
--- unsolicited or in response to a 'GetBlocks' message.
-data Inv =
-    Inv {
-        -- | Inventory vectors
-          invList :: ![InvVector]
-        } deriving (Eq, Show, Read)
-
-instance NFData Inv where
-    rnf (Inv l) = rnf l
-
-instance Serialize Inv where
-
-    get = Inv <$> (repList =<< get)
-      where
-        repList (VarInt c) = replicateM (fromIntegral c) get
-
-    put (Inv xs) = do
-        put $ VarInt $ fromIntegral $ length xs
-        forM_ xs put
-
--- | Data type identifying the type of an inventory vector.
-data InvType
-    = InvError -- ^ Error. Data containing this type can be ignored.
-    | InvTx    -- ^ InvVector hash is related to a transaction
-    | InvBlock -- ^ InvVector hash is related to a block
-    | InvMerkleBlock -- ^ InvVector has is related to a merkle block
-    deriving (Eq, Show, Read)
-
-instance NFData InvType where rnf x = seq x ()
-
-instance Serialize InvType where
-
-    get = go =<< getWord32le
-      where
-        go x = case x of
-            0 -> return InvError
-            1 -> return InvTx
-            2 -> return InvBlock
-            3 -> return InvMerkleBlock
-            _ -> fail "bitcoinGet InvType: Invalid Type"
-
-    put x = putWord32le $ case x of
-                InvError       -> 0
-                InvTx          -> 1
-                InvBlock       -> 2
-                InvMerkleBlock -> 3
-
--- | Invectory vectors represent hashes identifying objects such as a 'Block'
--- or a 'Tx'. They are sent inside messages to notify other peers about
--- new data or data they have requested.
-data InvVector =
-    InvVector {
-                -- | Type of the object referenced by this inventory vector
-                invType :: !InvType
-                -- | Hash of the object referenced by this inventory vector
-              , invHash :: !Hash256
-              } deriving (Eq, Show, Read)
-
-instance NFData InvVector where
-    rnf (InvVector t h) = rnf t `seq` rnf h
-
-instance Serialize InvVector where
-    get = InvVector <$> get <*> get
-    put (InvVector t h) = put t >> put h
-
--- | Data type describing a bitcoin network address. Addresses are stored in
--- IPv6. IPv4 addresses are mapped to IPv6 using IPv4 mapped IPv6 addresses:
--- <http://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses>. Sometimes,
--- timestamps are sent together with the 'NetworkAddress' such as in the 'Addr'
--- data type.
-data NetworkAddress =
-    NetworkAddress {
-                   -- | Bitmask of services available for this address
-                     naServices :: !Word64
-                   -- | IPv6 address and port
-                   , naAddress  :: !SockAddr
-                   } deriving (Eq, Show)
-
-instance NFData NetworkAddress where
-    rnf NetworkAddress{..} = rnf naServices `seq` naAddress `seq` ()
-
-instance Serialize NetworkAddress where
-
-    get = NetworkAddress <$> getWord64le
-                         <*> getAddrPort
-      where
-        getAddrPort = do
-            a <- getWord32be
-            b <- getWord32be
-            c <- getWord32be
-            if a == 0x00000000 && b == 0x00000000 && c == 0x0000ffff
-              then do
-                d <- getWord32host
-                p <- getWord16be
-                return $ SockAddrInet (fromIntegral p) d
-              else do
-                d <- getWord32be
-                p <- getWord16be
-                return $ SockAddrInet6 (fromIntegral p) 0 (a,b,c,d) 0
-
-    put (NetworkAddress s (SockAddrInet6 p _ (a,b,c,d) _)) = do
-        putWord64le s
-        putWord32be a
-        putWord32be b
-        putWord32be c
-        putWord32be d
-        putWord16be (fromIntegral p)
-
-    put (NetworkAddress s (SockAddrInet p a)) = do
-        putWord64le s
-        putWord32be 0x00000000
-        putWord32be 0x00000000
-        putWord32be 0x0000ffff
-        putWord32host a
-        putWord16be (fromIntegral p)
-
-    put _ = error "NetworkAddress can onle be IPv4 or IPv6"
-
--- | A 'NotFound' message is returned as a response to a 'GetData' message
--- whe one of the requested objects could not be retrieved. This could happen,
--- for example, if a tranasaction was requested and was not available in the
--- memory pool of the receiving node.
-data NotFound =
-    NotFound {
-             -- | Inventory vectors related to this request
-               notFoundList :: ![InvVector]
-             } deriving (Eq, Show, Read)
-
-instance NFData NotFound where
-    rnf (NotFound l) = rnf l
-
-instance Serialize NotFound where
-
-    get = NotFound <$> (repList =<< get)
-      where
-        repList (VarInt c) = replicateM (fromIntegral c) get
-
-    put (NotFound xs) = do
-        put $ VarInt $ fromIntegral $ length xs
-        forM_ xs put
-
--- | A Ping message is sent to bitcoin peers to check if a TCP\/IP connection
--- is still valid.
-newtype Ping =
-    Ping {
-           -- | A random nonce used to identify the recipient of the ping
-           -- request once a Pong response is received.
-           pingNonce :: Word64
-         } deriving (Eq, Show, Read)
-
-instance NFData Ping where
-    rnf (Ping n) = rnf n
-
--- | A Pong message is sent as a response to a ping message.
-newtype Pong =
-    Pong {
-           -- | When responding to a Ping request, the nonce from the Ping
-           -- is copied in the Pong response.
-           pongNonce :: Word64
-         } deriving (Eq, Show, Read)
-
-instance NFData Pong where
-    rnf (Pong n) = rnf n
-
-instance Serialize Ping where
-    get = Ping <$> getWord64le
-    put (Ping n) = putWord64le n
-
-instance Serialize Pong where
-    get = Pong <$> getWord64le
-    put (Pong n) = putWord64le n
-
--- | The reject message is sent when messages are rejected by a peer.
-data Reject =
-    Reject {
-             -- | Type of message rejected
-             rejectMessage :: !MessageCommand
-             -- | Code related to the rejected message
-           , rejectCode    :: !RejectCode
-             -- | Text version of rejected reason
-           , rejectReason  :: !VarString
-             -- | Optional extra data provided by some errors
-           , rejectData    :: !ByteString
-           } deriving (Eq, Show, Read)
-
-
-data RejectCode
-    = RejectMalformed
-    | RejectInvalid
-    | RejectObsolete
-    | RejectDuplicate
-    | RejectNonStandard
-    | RejectDust
-    | RejectInsufficientFee
-    | RejectCheckpoint
-    deriving (Eq, Show, Read)
-
-instance Serialize RejectCode where
-
-    get = getWord8 >>= \code -> case code of
-        0x01 -> return RejectMalformed
-        0x10 -> return RejectInvalid
-        0x11 -> return RejectObsolete
-        0x12 -> return RejectDuplicate
-        0x40 -> return RejectNonStandard
-        0x41 -> return RejectDust
-        0x42 -> return RejectInsufficientFee
-        0x43 -> return RejectCheckpoint
-        _    -> fail $ unwords
-            [ "Reject get: Invalid code"
-            , show code
-            ]
-
-    put code = putWord8 $ case code of
-        RejectMalformed       -> 0x01
-        RejectInvalid         -> 0x10
-        RejectObsolete        -> 0x11
-        RejectDuplicate       -> 0x12
-        RejectNonStandard     -> 0x40
-        RejectDust            -> 0x41
-        RejectInsufficientFee -> 0x42
-        RejectCheckpoint      -> 0x43
-
--- | Convenience function to build a Reject message
-reject :: MessageCommand -> RejectCode -> ByteString -> Reject
-reject cmd code reason =
-    Reject cmd code (VarString reason) BS.empty
-
-instance Serialize Reject where
-
-    get = get >>= \(VarString bs) -> case stringToCommand bs of
-        Just cmd -> Reject cmd <$> get <*> get <*> maybeData
-        _ -> fail $ unwords
-            ["Reason get: Invalid message command" ,cs bs]
-      where
-        maybeData = isEmpty >>= \done ->
-            if done then return BS.empty else getByteString 32
-
-    put (Reject cmd code reason dat) = do
-        put $ VarString $ commandToString cmd
-        put code
-        put reason
-        unless (BS.null dat) $ putByteString dat
-
--- | Data type representing a variable length integer. The 'VarInt' type
--- usually precedes an array or a string that can vary in length.
-newtype VarInt = VarInt { getVarInt :: Word64 }
-    deriving (Eq, Show, Read)
-
-instance NFData VarInt where
-    rnf (VarInt w) = rnf w
-
-instance Serialize VarInt where
-
-    get = VarInt <$> ( getWord8 >>= go )
-      where
-        go 0xff = getWord64le
-        go 0xfe = fromIntegral <$> getWord32le
-        go 0xfd = fromIntegral <$> getWord16le
-        go x    = fromIntegral <$> return x
-
-    put (VarInt x)
-        | x < 0xfd =
-            putWord8 $ fromIntegral x
-        | x <= 0xffff = do
-            putWord8 0xfd
-            putWord16le $ fromIntegral x
-        | x <= 0xffffffff = do
-            putWord8 0xfe
-            putWord32le $ fromIntegral x
-        | otherwise = do
-            putWord8 0xff
-            putWord64le x
-
--- | Data type for variable length strings. Variable length strings are
--- serialized as a 'VarInt' followed by a bytestring.
-newtype VarString = VarString { getVarString :: ByteString }
-    deriving (Eq, Show, Read)
-
-instance NFData VarString where
-    rnf (VarString s) = rnf s
-
-instance Serialize VarString where
-
-    get = VarString <$> (readBS =<< get)
-      where
-        readBS (VarInt len) = getByteString (fromIntegral len)
-
-    put (VarString bs) = do
-        put $ VarInt $ fromIntegral $ BS.length bs
-        putByteString bs
-
--- | When a bitcoin node creates an outgoing connection to another node,
--- the first message it will send is a 'Version' message. The other node
--- will similarly respond with it's own 'Version' message.
-data Version =
-    Version {
-              -- | Protocol version being used by the node.
-              version     :: !Word32
-              -- | Bitmask of features to enable for this connection.
-            , services    :: !Word64
-              -- | UNIX timestamp
-            , timestamp   :: !Word64
-              -- | Network address of the node receiving this message.
-            , addrRecv    :: !NetworkAddress
-              -- | Network address of the node sending this message.
-            , addrSend    :: !NetworkAddress
-              -- | Randomly generated identifying sent with every version
-              -- message. This nonce is used to detect connection to self.
-            , verNonce    :: !Word64
-              -- | User agent
-            , userAgent   :: !VarString
-              -- | The height of the last block received by the sending node.
-            , startHeight :: !Word32
-              -- | Wether the remote peer should announce relaying transactions
-              -- or not. This feature is enabled since version >= 70001. See
-              -- BIP37 for more details.
-            , relay       :: !Bool
-            } deriving (Eq, Show)
-
-instance NFData Version where
-    rnf Version{..} =
-        rnf version `seq`
-        rnf services `seq`
-        rnf timestamp `seq`
-        rnf addrRecv `seq`
-        rnf addrSend `seq`
-        rnf verNonce `seq`
-        rnf userAgent `seq`
-        rnf startHeight `seq`
-        rnf relay
-
-instance Serialize Version where
-
-    get = Version <$> getWord32le
-                  <*> getWord64le
-                  <*> getWord64le
-                  <*> get
-                  <*> get
-                  <*> getWord64le
-                  <*> get
-                  <*> getWord32le
-                  <*> (go =<< isEmpty)
-      where
-        go True  = return True
-        go False = getBool
-
-    put (Version v s t ar as n ua sh r) = do
-        putWord32le v
-        putWord64le s
-        putWord64le t
-        put         ar
-        put         as
-        putWord64le n
-        put         ua
-        putWord32le sh
-        putBool     r
-
-getBool :: Get Bool
-getBool = go =<< getWord8
-  where
-    go 0 = return False
-    go _ = return True
-
-putBool :: Bool -> Put
-putBool True  = putWord8 1
-putBool False = putWord8 0
-
--- | A 'MessageCommand' is included in a 'MessageHeader' in order to identify
--- the type of message present in the payload. This allows the message
--- de-serialization code to know how to decode a particular message payload.
--- Every valid 'Message' constructor has a corresponding 'MessageCommand'
--- constructor.
-data MessageCommand
-    = MCVersion
-    | MCVerAck
-    | MCAddr
-    | MCInv
-    | MCGetData
-    | MCNotFound
-    | MCGetBlocks
-    | MCGetHeaders
-    | MCTx
-    | MCBlock
-    | MCMerkleBlock
-    | MCHeaders
-    | MCGetAddr
-    | MCFilterLoad
-    | MCFilterAdd
-    | MCFilterClear
-    | MCPing
-    | MCPong
-    | MCAlert
-    | MCMempool
-    | MCReject
-    deriving (Eq, Show, Read)
-
-instance NFData MessageCommand where rnf x = seq x ()
-
-instance Serialize MessageCommand where
-
-    get = go =<< getByteString 12
-      where
-        go bs = case stringToCommand $ unpackCommand bs of
-            Just cmd -> return cmd
-            Nothing  -> fail "get MessageCommand : Invalid command"
-
-    put mc = putByteString $ packCommand $ commandToString mc
-
-
-stringToCommand :: ByteString -> Maybe MessageCommand
-stringToCommand str = case str of
-    "version"     -> Just MCVersion
-    "verack"      -> Just MCVerAck
-    "addr"        -> Just MCAddr
-    "inv"         -> Just MCInv
-    "getdata"     -> Just MCGetData
-    "notfound"    -> Just MCNotFound
-    "getblocks"   -> Just MCGetBlocks
-    "getheaders"  -> Just MCGetHeaders
-    "tx"          -> Just MCTx
-    "block"       -> Just MCBlock
-    "merkleblock" -> Just MCMerkleBlock
-    "headers"     -> Just MCHeaders
-    "getaddr"     -> Just MCGetAddr
-    "filterload"  -> Just MCFilterLoad
-    "filteradd"   -> Just MCFilterAdd
-    "filterclear" -> Just MCFilterClear
-    "ping"        -> Just MCPing
-    "pong"        -> Just MCPong
-    "alert"       -> Just MCAlert
-    "mempool"     -> Just MCMempool
-    "reject"      -> Just MCReject
-    _             -> Nothing
-
-commandToString :: MessageCommand -> ByteString
-commandToString mc = case mc of
-    MCVersion     -> "version"
-    MCVerAck      -> "verack"
-    MCAddr        -> "addr"
-    MCInv         -> "inv"
-    MCGetData     -> "getdata"
-    MCNotFound    -> "notfound"
-    MCGetBlocks   -> "getblocks"
-    MCGetHeaders  -> "getheaders"
-    MCTx          -> "tx"
-    MCBlock       -> "block"
-    MCMerkleBlock -> "merkleblock"
-    MCHeaders     -> "headers"
-    MCGetAddr     -> "getaddr"
-    MCFilterLoad  -> "filterload"
-    MCFilterAdd   -> "filteradd"
-    MCFilterClear -> "filterclear"
-    MCPing        -> "ping"
-    MCPong        -> "pong"
-    MCAlert       -> "alert"
-    MCMempool     -> "mempool"
-    MCReject      -> "reject"
-
-packCommand :: ByteString -> ByteString
-packCommand s = BS.take 12 $
-    s `mappend` C.replicate 12 '\NUL'
-
-unpackCommand :: ByteString -> ByteString
-unpackCommand = BS.takeWhile (/= 0)
-
diff --git a/Network/Haskoin/Script.hs b/Network/Haskoin/Script.hs
deleted file mode 100644
--- a/Network/Haskoin/Script.hs
+++ /dev/null
@@ -1,73 +0,0 @@
-{-|
-  This package provides functions for parsing and evaluating bitcoin
-  transaction scripts. Data types are provided for building and
-  deconstructing all of the standard input and output script types.
--}
-module Network.Haskoin.Script
-(
-  -- *Scripts
-  -- | More informations on scripts is available here:
-  -- <http://en.bitcoin.it/wiki/Script>
-  Script(..)
-, ScriptOp(..)
-, PushDataType(..)
-, opPushData
-
-  -- *Script Parsing
-  -- **Script Outputs
-, ScriptOutput(..)
-, encodeOutput
-, encodeOutputBS
-, decodeOutput
-, decodeOutputBS
-, isPayPK
-, isPayPKHash
-, isPayMulSig
-, isPayScriptHash
-, scriptAddr
-, sortMulSig
-
-  -- **Script Inputs
-, ScriptInput(..)
-, SimpleInput(..)
-, RedeemScript
-, encodeInput
-, encodeInputBS
-, decodeInput
-, decodeInputBS
-, isSpendPK
-, isSpendPKHash
-, isSpendMulSig
-, isScriptHashInput
-
-  -- * Helpers
-, inputAddress
-, outputAddress
-, intToScriptOp
-, scriptOpToInt
-
--- *SigHash
--- | For additional information on sighashes, see:
--- <http://en.bitcoin.it/wiki/OP_CHECKSIG>
-, SigHash(..)
-, txSigHash
-, encodeSigHash32
-, isSigAll
-, isSigNone
-, isSigSingle
-, isSigUnknown
-, TxSignature(..)
-, encodeSig
-, decodeSig
-, decodeCanonicalSig
-
--- *Evaluation
-, evalScript
-, verifySpend
-, SigCheck
-) where
-
-import Network.Haskoin.Script.Types
-import Network.Haskoin.Script.Parser
-import Network.Haskoin.Script.SigHash
-import Network.Haskoin.Script.Evaluator
diff --git a/Network/Haskoin/Script/Evaluator.hs b/Network/Haskoin/Script/Evaluator.hs
deleted file mode 100644
--- a/Network/Haskoin/Script/Evaluator.hs
+++ /dev/null
@@ -1,812 +0,0 @@
-{-# LANGUAGE LambdaCase #-}
-{-|
-
-Module providing Bitcoin script evaluation.  See
-<https://github.com/bitcoin/bitcoin/blob/master/src/script.cpp>
-EvalScript and <https://en.bitcoin.it/wiki/Script>
-
--}
-module Network.Haskoin.Script.Evaluator
-(
--- * Script evaluation
-  verifySpend
-, evalScript
-, SigCheck
-, Flag
--- * Evaluation data types
-, ProgramData
-, Stack
--- * Helper functions
-, encodeInt
-, decodeInt
-, decodeFullInt
-, cltvEncodeInt
-, cltvDecodeInt
-, encodeBool
-, decodeBool
-, runStack
-, checkStack
-, dumpScript
-, dumpStack
-, execScript
-) where
-
-import           Control.Monad.Except
-import           Control.Monad.Identity
-import           Control.Monad.Reader
-import           Control.Monad.State
-import           Data.Bits                         (clearBit, setBit, shiftL,
-                                                    shiftR, testBit, (.&.))
-import           Data.ByteString                   (ByteString)
-import qualified Data.ByteString                   as BS
-import           Data.Either                       (rights)
-import           Data.Int                          (Int64)
-import           Data.Maybe                        (isJust, mapMaybe)
-import           Data.Serialize                    (decode, encode)
-import           Data.String.Conversions           (cs)
-import           Data.Word                         (Word64, Word32, Word8)
-import           Network.Haskoin.Crypto
-import           Network.Haskoin.Script.SigHash
-import           Network.Haskoin.Script.Types
-import           Network.Haskoin.Transaction.Types
-import           Network.Haskoin.Util
-
-maxScriptSize :: Int
-maxScriptSize = 10000
-
-maxScriptElementSize :: Int
-maxScriptElementSize = 520
-
-maxStackSize :: Int
-maxStackSize = 1000
-
-maxOpcodes :: Int
-maxOpcodes = 200
-
-maxKeysMultisig :: Int
-maxKeysMultisig = 20
-
-data Flag = P2SH
-          | STRICTENC
-          | DERSIG
-          | LOW_S
-          | NULLDUMMY
-          | SIGPUSHONLY
-          | MINIMALDATA
-          | DISCOURAGE_UPGRADABLE_NOPS
-     deriving ( Show, Read, Eq )
-
-type FlagSet = [ Flag ]
-
-data EvalError =
-    EvalError String
-    | ProgramError String ProgramData
-    | StackError ScriptOp
-    | DisabledOp ScriptOp
-
-instance Show EvalError where
-    show (EvalError m) = m
-    show (ProgramError m prog) = m ++ " - ProgramData: " ++ show prog
-    show (StackError op) = show op ++ ": Stack Error"
-    show (DisabledOp op) = show op ++ ": disabled"
-
-type StackValue = [Word8]
-type AltStack = [StackValue]
-type Stack = [StackValue]
-type HashOps = [ScriptOp] -- the code that is verified by OP_CHECKSIG
-
--- | Defines the type of function required by script evaluating
--- functions to check transaction signatures.
-type SigCheck = [ScriptOp] -> TxSignature -> PubKey -> Bool
-
--- | Data type of the evaluation state.
-data ProgramData = ProgramData {
-    stack        :: Stack,
-    altStack     :: AltStack,
-    hashOps      :: HashOps,
-    sigCheck     :: SigCheck,
-    opCount      :: Int
-}
-
-dumpOp :: ScriptOp -> ByteString
-dumpOp (OP_PUSHDATA payload optype) = mconcat
-  [ "OP_PUSHDATA(", cs (show optype), ")", " 0x", encodeHex payload ]
-dumpOp op = cs $ show op
-
-dumpList :: [ByteString] -> ByteString
-dumpList xs = mconcat [ "[", BS.intercalate "," xs, "]" ]
-
-dumpScript :: [ScriptOp] -> ByteString
-dumpScript script = dumpList $ map dumpOp script
-
-dumpStack :: Stack -> ByteString
-dumpStack s = dumpList $ map (encodeHex . BS.pack) s
-
--- TODO: Test
-instance Show ProgramData where
-    show p = "stack: " ++ (cs $ dumpStack $ stack p)
-
-type ProgramState = ExceptT EvalError Identity
-type IfStack = [Bool]
-
--- | Monad of actions independent of conditional statements.
-type StackOperation = ReaderT FlagSet ( StateT ProgramData ProgramState )
--- | Monad of actions which taking if statements into account.
--- Separate state type from StackOperation for type safety
-type Program a = StateT IfStack StackOperation a
-
-evalStackOperation :: StackOperation a -> ProgramData -> FlagSet -> Either EvalError a
-evalStackOperation m s f = runIdentity . runExceptT $ evalStateT ( runReaderT m f ) s
-
-evalProgram :: Program a                      -- ^ ProgramData monad
-            -> [ Bool ]                       -- ^ Initial if state stack
-            -> ProgramData                    -- ^ Initial computation data
-            -> FlagSet                        -- ^ Evaluation Flags
-            -> Either EvalError a
-evalProgram m s = evalStackOperation ( evalStateT m s )
-
---------------------------------------------------------------------------------
--- Error utils
-
-programError :: String -> StackOperation a
-programError s = get >>= throwError . ProgramError s
-
-disabled :: ScriptOp -> StackOperation ()
-disabled op = throwError . DisabledOp $ op
-
---------------------------------------------------------------------------------
--- Type Conversions
-
--- | Encoding function for the stack value format of integers.  Most
--- significant bit defines sign.
--- Note that this function will encode any Int64 into a StackValue,
--- thus producing stack-encoded integers which are not valid numeric
--- opcodes, as they exceed 4 bytes in length.
-encodeInt :: Int64 -> StackValue
-encodeInt i = prefix $ encod (fromIntegral $ abs i) []
-    where encod :: Word64 -> StackValue -> StackValue
-          encod 0 bytes = bytes
-          encod j bytes = fromIntegral j:encod (j `shiftR` 8) bytes
-          prefix :: StackValue -> StackValue
-          prefix [] = []
-          prefix xs | testBit (last xs) 7 = prefix $ xs ++ [0]
-                    | i < 0 = init xs ++ [setBit (last xs) 7]
-                    | otherwise = xs
-
--- | Decode an Int64 from the stack value integer format.
--- Inverse of `encodeInt`.
--- Note that only integers decoded by 'decodeInt' are valid
--- numeric opcodes (numeric opcodes can only be up to 4 bytes in size).
--- However, in the case of eg. CHECKLOCKTIMEVERIFY, we need to
--- be able to encode and decode stack integers up to
--- (maxBound :: Word32), which are 5 bytes.
-decodeFullInt :: StackValue -> Maybe Int64
-decodeFullInt bytes
-    | length bytes > 8 = Nothing
-    | otherwise = Just $ sign' (decodeW bytes)
-        where decodeW [] = 0
-              decodeW [x] = fromIntegral $ clearBit x 7
-              decodeW (x:xs) = fromIntegral x + decodeW xs `shiftL` 8
-              sign' i | null bytes = 0
-                    | testBit (last bytes) 7 = -i
-                    | otherwise = i
-
--- | Used for decoding numeric opcodes. Will not return
--- an integer that takes up more than
--- 4 bytes on the stack (the size limit for numeric opcodes).
--- The naming is kept for backwards compatibility.
-decodeInt :: StackValue -> Maybe Int64
-decodeInt bytes | length bytes > 4 = Nothing
-                | otherwise = decodeFullInt bytes
-
--- | Decode the integer argument to OP_CHECKLOCKTIMEVERIFY (CLTV)
--- from a stack value.
--- The full uint32 range is needed in order to represent timestamps
--- for use with CLTV. Reference:
--- https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki#Detailed_Specification
-cltvDecodeInt :: StackValue -> Maybe Word32
-cltvDecodeInt bytes
-    | length bytes > 5 = Nothing
-    | otherwise = decodeFullInt bytes >>= uint32Bounds
-  where
-    uint32Bounds :: Int64 -> Maybe Word32
-    uint32Bounds i64
-        | i64 < 0 || i64 > fromIntegral (maxBound :: Word32) = Nothing
-        | otherwise = Just $ fromIntegral i64
-
--- | Helper function for encoding the argument to OP_CHECKLOCKTIMEVERIFY
-cltvEncodeInt :: Word32 -> StackValue
-cltvEncodeInt = encodeInt . fromIntegral
-
--- | Conversion of StackValue to Bool (true if non-zero).
-decodeBool :: StackValue -> Bool
-decodeBool []     = False
-decodeBool [0x00] = False
-decodeBool [0x80] = False
-decodeBool (0x00:vs) = decodeBool vs
-decodeBool _ = True
-
-encodeBool :: Bool -> StackValue
-encodeBool True = [1]
-encodeBool False = []
-
-constValue :: ScriptOp -> Maybe StackValue
-constValue op = case op of
-    OP_0  -> Just $ encodeInt 0
-    OP_1  -> Just $ encodeInt 1
-    OP_2  -> Just $ encodeInt 2
-    OP_3  -> Just $ encodeInt 3
-    OP_4  -> Just $ encodeInt 4
-    OP_5  -> Just $ encodeInt 5
-    OP_6  -> Just $ encodeInt 6
-    OP_7  -> Just $ encodeInt 7
-    OP_8  -> Just $ encodeInt 8
-    OP_9  -> Just $ encodeInt 9
-    OP_10 -> Just $ encodeInt 10
-    OP_11 -> Just $ encodeInt 11
-    OP_12 -> Just $ encodeInt 12
-    OP_13 -> Just $ encodeInt 13
-    OP_14 -> Just $ encodeInt 14
-    OP_15 -> Just $ encodeInt 15
-    OP_16 -> Just $ encodeInt 16
-    OP_1NEGATE -> Just $ encodeInt $ -1
-    (OP_PUSHDATA string _) -> Just $ BS.unpack string
-    _ -> Nothing
-
-
--- | Check if OpCode is constant
-isConstant :: ScriptOp -> Bool
-isConstant = isJust . constValue
-
--- | Check if OpCode is disabled
-isDisabled :: ScriptOp -> Bool
-isDisabled op = op `elem` [ OP_CAT
-                          , OP_SUBSTR
-                          , OP_LEFT
-                          , OP_RIGHT
-                          , OP_INVERT
-                          , OP_AND
-                          , OP_OR
-                          , OP_XOR
-                          , OP_2MUL
-                          , OP_2DIV
-                          , OP_MUL
-                          , OP_DIV
-                          , OP_MOD
-                          , OP_LSHIFT
-                          , OP_RSHIFT
-                          , OP_VER
-                          , OP_VERIF
-                          , OP_VERNOTIF ]
-
--- | Check if OpCode counts towards opcount limit
-
-countOp :: ScriptOp -> Bool
-countOp op | isConstant op     = False
-           | op == OP_RESERVED = False
-           | otherwise         = True
-
-popInt :: StackOperation Int64
-popInt = minimalStackValEnforcer >> decodeInt <$> popStack >>= \case
-    Nothing -> programError "popInt: data > nMaxNumSize"
-    Just i -> return i
-
-pushInt :: Int64 -> StackOperation ()
-pushInt = pushStack . encodeInt
-
-popBool :: StackOperation Bool
-popBool = decodeBool <$> popStack
-
-pushBool :: Bool -> StackOperation ()
-pushBool = pushStack . encodeBool
-
-opToSv :: StackValue -> BS.ByteString
-opToSv = BS.pack
-
-bsToSv :: BS.ByteString -> StackValue
-bsToSv = BS.unpack
-
---------------------------------------------------------------------------------
--- Stack Primitives
-
-getStack :: StackOperation Stack
-getStack = stack <$> get
-
-getCond :: Program [Bool]
-getCond = get
-
-popCond :: Program Bool
-popCond = get >>= \condStack -> case condStack of
-    [] -> lift $ programError "popCond: empty condStack"
-    (x:xs) -> put xs >> return x
-
-pushCond :: Bool -> Program ()
-pushCond c = get >>= \s ->
-    put (c:s)
-
-flipCond :: Program ()
-flipCond = popCond >>= pushCond . not
-
-withStack :: StackOperation Stack
-withStack = getStack >>= \case
-    [] -> stackError
-    s  -> return s
-
-putStack :: Stack -> StackOperation ()
-putStack st = modify $ \p -> p { stack = st }
-
-prependStack :: Stack -> StackOperation ()
-prependStack s = getStack >>= \s' -> putStack $ s ++ s'
-
-checkPushData :: ScriptOp -> StackOperation ()
-checkPushData (OP_PUSHDATA v _) | BS.length v > fromIntegral maxScriptElementSize
-                                  = programError "OP_PUSHDATA > maxScriptElementSize"
-                                | otherwise = return ()
-checkPushData _ = return ()
-
-checkStackSize :: StackOperation ()
-checkStackSize = do n <- length <$> stack <$> get
-                    m <- length <$> altStack <$> get
-                    when ((n + m) > fromIntegral maxStackSize) $
-                         programError "stack > maxStackSize"
-
-pushStack :: StackValue -> StackOperation ()
-pushStack v = getStack >>= \s -> putStack (v:s)
-
-popStack :: StackOperation StackValue
-popStack = withStack >>= \(s:ss) -> putStack ss >> return s
-
-popStackN :: Integer -> StackOperation [StackValue]
-popStackN n | n < 0     = programError "popStackN: negative argument"
-            | n == 0    = return []
-            | otherwise = (:) <$> popStack <*> popStackN (n - 1)
-
-pickStack :: Bool -> Int -> StackOperation ()
-pickStack remove n = do
-    st <- getStack
-
-    when (n < 0) $
-        programError "pickStack: n < 0"
-    when (n > length st - 1) $
-        programError "pickStack: n > size"
-
-    let v = st !! n
-    when remove $ putStack $ take n st ++ drop (n+1) st
-    pushStack v
-
-getHashOps :: StackOperation HashOps
-getHashOps = hashOps <$> get
-
--- | Function to track the verified OPs signed by OP_CHECK(MULTI) sig.
--- Dependent on the sequence of `OP_CODESEPARATOR`
-dropHashOpsSeparatedCode :: StackOperation ()
-dropHashOpsSeparatedCode = modify $ \p ->
-   let tryDrop = dropWhile ( /= OP_CODESEPARATOR ) $ hashOps p in
-   case tryDrop of
-     -- If no OP_CODESEPARATOR, take the whole script.  This case is
-     -- possible when there is no OP_CODESEPARATOR in scriptPubKey but
-     -- one exists in scriptSig
-     [] -> p
-     _  -> p { hashOps = tail tryDrop }
-
--- | Filters out `OP_CODESEPARATOR` from the output script used by
--- OP_CHECK(MULTI)SIG
-preparedHashOps :: StackOperation HashOps
-preparedHashOps = filter ( /= OP_CODESEPARATOR ) <$> getHashOps
-
--- | Removes any PUSHDATA that contains the signatures.  Used in
--- CHECK(MULTI)SIG so that signatures can be contained in output
--- scripts.  See FindAndDelete() in Bitcoin Core.
-findAndDelete :: [ StackValue ] -> [ ScriptOp ] -> [ ScriptOp ]
-findAndDelete [] ops = ops
-findAndDelete (s:ss) ops = let pushOp = opPushData . opToSv $ s in
-  findAndDelete ss $ filter ( /= pushOp ) ops
-
-checkMultiSig :: SigCheck -- ^ Signature checking function
-              -> [ StackValue ] -- ^ PubKeys
-              -> [ StackValue ] -- ^ Signatures
-              -> [ ScriptOp ]   -- ^ CODESEPARATOR'd hashops
-              -> Bool
-checkMultiSig f encPubKeys encSigs hOps =
-  let pubKeys = mapMaybe ( decodeToMaybe . opToSv ) encPubKeys
-      sigs = rights $ map ( decodeSig . opToSv ) encSigs
-      cleanHashOps = findAndDelete encSigs hOps
-  in (length sigs == length encSigs) && -- check for bad signatures
-     orderedSatisfy (f cleanHashOps) sigs pubKeys
-
--- | Tests whether a function is satisfied for every a with some b "in
--- order".  By "in order" we mean, if a pair satisfies the function,
--- any other satisfying pair must be deeper in each list.  Designed to
--- return as soon as the result is known to minimize expensive
--- function calls.  Used in checkMultiSig to verify signature/pubKey
--- pairs with a values as signatures and b values as pubkeys
-orderedSatisfy :: ( a -> b -> Bool )
-                    -> [ a ]
-                    -> [ b ]
-                    -> Bool
-orderedSatisfy _ [] _ = True
-orderedSatisfy _ (_:_) [] = False
-orderedSatisfy f x@(a:as) y@(b:bs) | length x > length y = False
-                                   | f a b     = orderedSatisfy f as bs
-                                   | otherwise = orderedSatisfy f x bs
-
-tStack1 :: (StackValue -> Stack) -> StackOperation ()
-tStack1 f = f <$> popStack >>= prependStack
-
-tStack2 :: (StackValue -> StackValue -> Stack) -> StackOperation ()
-tStack2 f = f <$> popStack <*> popStack >>= prependStack
-
-tStack3 :: (StackValue -> StackValue -> StackValue -> Stack) -> StackOperation ()
-tStack3 f = f <$> popStack <*> popStack <*> popStack >>= prependStack
-
-tStack4 :: (StackValue -> StackValue -> StackValue -> StackValue -> Stack)
-            -> StackOperation ()
-tStack4 f = f <$> popStack <*> popStack <*> popStack <*> popStack
-              >>= prependStack
-
-tStack6 :: (StackValue -> StackValue -> StackValue ->
-            StackValue -> StackValue -> StackValue -> Stack) -> StackOperation ()
-tStack6 f = f <$> popStack <*> popStack <*> popStack
-              <*> popStack <*> popStack <*> popStack >>= prependStack
-
-arith1 :: (Int64 -> Int64) -> StackOperation ()
-arith1 f = do
-    i <- popInt
-    pushStack $ encodeInt (f i)
-
-arith2 :: (Int64 -> Int64 -> Int64) -> StackOperation ()
-arith2 f = do
-    i <- popInt
-    j <- popInt
-    pushStack $ encodeInt (f i j)
-
-stackError :: StackOperation a
-stackError = programError "stack error"
-
--- AltStack Primitives
-
-pushAltStack :: StackValue -> StackOperation ()
-pushAltStack op = modify $ \p -> p { altStack = op:altStack p }
-
-popAltStack :: StackOperation StackValue
-popAltStack = get >>= \p -> case altStack p of
-    a:as -> put p { altStack = as } >> return a
-    []   -> programError "popAltStack: empty stack"
-
-
-incrementOpCount :: Int -> StackOperation ()
-incrementOpCount i | i > maxOpcodes = programError "reached opcode limit"
-                   | otherwise      = modify $ \p -> p { opCount = i + 1 }
-
-nopDiscourager :: StackOperation ()
-nopDiscourager = do
-    flgs <- ask
-    if DISCOURAGE_UPGRADABLE_NOPS `elem` flgs
-        then programError "Discouraged OP used."
-        else return ()
-
--- Instruction Evaluation
-eval :: ScriptOp -> StackOperation ()
-eval OP_NOP     = return ()
-eval OP_NOP1    = nopDiscourager >> return ()
-eval OP_NOP2    = nopDiscourager >> return ()
-eval OP_NOP3    = nopDiscourager >> return ()
-eval OP_NOP4    = nopDiscourager >> return ()
-eval OP_NOP5    = nopDiscourager >> return ()
-eval OP_NOP6    = nopDiscourager >> return ()
-eval OP_NOP7    = nopDiscourager >> return ()
-eval OP_NOP8    = nopDiscourager >> return ()
-eval OP_NOP9    = nopDiscourager >> return ()
-eval OP_NOP10   = nopDiscourager >> return ()
-
-eval OP_VERIFY = popBool >>= \case
-    True  -> return ()
-    False -> programError "OP_VERIFY failed"
-
-eval OP_RETURN = programError "explicit OP_RETURN"
-
--- Stack
-
-eval OP_TOALTSTACK = popStack >>= pushAltStack
-eval OP_FROMALTSTACK = popAltStack >>= pushStack
-eval OP_IFDUP   = tStack1 $ \a -> if decodeBool a then [a, a] else [a]
-eval OP_DEPTH   = getStack >>= pushStack . encodeInt . fromIntegral . length
-eval OP_DROP    = void popStack
-eval OP_DUP     = tStack1 $ \a -> [a, a]
-eval OP_NIP     = tStack2 $ \a _ -> [a]
-eval OP_OVER    = tStack2 $ \a b -> [b, a, b]
-eval OP_PICK    = popInt >>= (pickStack False . fromIntegral)
-eval OP_ROLL    = popInt >>= (pickStack True . fromIntegral)
-eval OP_ROT     = tStack3 $ \a b c -> [c, a, b]
-eval OP_SWAP    = tStack2 $ \a b -> [b, a]
-eval OP_TUCK    = tStack2 $ \a b -> [a, b, a]
-eval OP_2DROP   = tStack2 $ \_ _ -> []
-eval OP_2DUP    = tStack2 $ \a b -> [a, b, a, b]
-eval OP_3DUP    = tStack3 $ \a b c -> [a, b, c, a, b, c]
-eval OP_2OVER   = tStack4 $ \a b c d -> [c, d, a, b, c, d]
-eval OP_2ROT    = tStack6 $ \a b c d e f -> [e, f, a, b, c, d]
-eval OP_2SWAP   = tStack4 $ \a b c d -> [c, d, a, b]
-
--- Splice
-
-eval OP_SIZE   = (fromIntegral . length <$> head <$> withStack) >>= pushInt
-
--- Bitwise Logic
-
-eval OP_EQUAL   = tStack2 $ \a b -> [encodeBool (a == b)]
-eval OP_EQUALVERIFY = eval OP_EQUAL >> eval OP_VERIFY
-
--- Arithmetic
-
-eval OP_1ADD    = arith1 (+1)
-eval OP_1SUB    = arith1 (subtract 1)
-eval OP_NEGATE  = arith1 negate
-eval OP_ABS     = arith1 abs
-eval OP_NOT         = arith1 $ \case 0 -> 1; _ -> 0
-eval OP_0NOTEQUAL   = arith1 $ \case 0 -> 0; _ -> 1
-eval OP_ADD     = arith2 (+)
-eval OP_SUB     = arith2 $ flip (-)
-eval OP_BOOLAND     = (&&) <$> ((0 /=) <$> popInt)
-                           <*> ((0 /=) <$> popInt) >>= pushBool
-eval OP_BOOLOR      = (||) <$> ((0 /=) <$> popInt)
-                           <*> ((0 /=) <$> popInt) >>= pushBool
-eval OP_NUMEQUAL    = (==) <$> popInt <*> popInt >>= pushBool
-eval OP_NUMEQUALVERIFY = eval OP_NUMEQUAL >> eval OP_VERIFY
-eval OP_NUMNOTEQUAL         = (/=) <$> popInt <*> popInt >>= pushBool
-eval OP_LESSTHAN            = (>)  <$> popInt <*> popInt >>= pushBool
-eval OP_GREATERTHAN         = (<)  <$> popInt <*> popInt >>= pushBool
-eval OP_LESSTHANOREQUAL     = (>=) <$> popInt <*> popInt >>= pushBool
-eval OP_GREATERTHANOREQUAL  = (<=) <$> popInt <*> popInt >>= pushBool
-eval OP_MIN     = min <$> popInt <*> popInt >>= pushInt
-eval OP_MAX     = max <$> popInt <*> popInt >>= pushInt
-eval OP_WITHIN  = within <$> popInt <*> popInt <*> popInt >>= pushBool
-                  where within y x a = (x <= a) && (a < y)
-
-eval OP_RIPEMD160 = tStack1 $ return . bsToSv . getHash160 . hash160 . opToSv
-eval OP_SHA1 = tStack1 $ return . bsToSv . getHash160 . sha1 . opToSv
-
-eval OP_SHA256 = tStack1 $ return . bsToSv . getHash256 . hash256 . opToSv
-eval OP_HASH160 = tStack1 $
-    return . bsToSv . getHash160 . hash160 . getHash256 . hash256 . opToSv
-eval OP_HASH256 = tStack1 $
-    return . bsToSv . getHash256 . doubleHash256  . opToSv
-eval OP_CODESEPARATOR = dropHashOpsSeparatedCode
-eval OP_CHECKSIG = do
-    pubKey <- popStack
-    sig <- popStack
-    checker <- sigCheck <$> get
-    hOps <- preparedHashOps
-    -- Reuse checkMultiSig code
-    pushBool $ checkMultiSig checker [ pubKey ] [ sig ] hOps
-
-eval OP_CHECKMULTISIG =
-    do nPubKeys <- fromIntegral <$> popInt
-       when (nPubKeys < 0 || nPubKeys > maxKeysMultisig)
-            $ programError $ "nPubKeys outside range: " ++ show nPubKeys
-       pubKeys <- popStackN $ toInteger nPubKeys
-
-       nSigs <- fromIntegral <$> popInt
-       when (nSigs < 0 || nSigs > nPubKeys)
-            $ programError $ "nSigs outside range: " ++ show nSigs
-       sigs <- popStackN $ toInteger nSigs
-
-       nullDummyEnforcer
-       void popStack -- spec bug
-       checker <- sigCheck <$> get
-       hOps <- preparedHashOps
-       pushBool $ checkMultiSig checker pubKeys sigs hOps
-       modify $ \p -> p { opCount = opCount p + length pubKeys }
-
-eval OP_CHECKSIGVERIFY      = eval OP_CHECKSIG      >> eval OP_VERIFY
-eval OP_CHECKMULTISIGVERIFY = eval OP_CHECKMULTISIG >> eval OP_VERIFY
-
-eval op = case constValue op of
-    Just sv -> minimalPushEnforcer op >> pushStack sv
-    Nothing -> programError $ "unexpected op " ++ show op
-
-minimalPushEnforcer :: ScriptOp -> StackOperation ()
-minimalPushEnforcer op = do
-    flgs <- ask
-    if not $ MINIMALDATA `elem` flgs
-        then return ()
-        else case checkMinimalPush op of
-            True -> return ()
-            False -> programError $ "Non-minimal data: " ++ (show op)
-
-checkMinimalPush :: ScriptOp -> Bool -- Putting in a maybe monad to avoid elif chain
-checkMinimalPush ( OP_PUSHDATA payload optype ) =
-  let l = BS.length payload
-      v = ( BS.unpack payload ) !! 0 in
-  if
-     (BS.null payload)                     -- Check if could have used OP_0
-     || (l == 1 && v <= 16 && v >= 1)   -- Could have used OP_{1,..,16}
-     || (l == 1 && v == 0x81)           -- Could have used OP_1NEGATE
-     || (l <= 75 && optype /= OPCODE)   -- Could have used direct push
-     || (l <= 255 && l > 75 && optype /= OPDATA1)
-     || (l > 255 && l <= 65535 && optype /= OPDATA2)
-  then False else True
-checkMinimalPush _ = True
-
--- | Checks the top of the stack for a minimal numeric representation
--- if flagged to do so
-minimalStackValEnforcer :: StackOperation ()
-minimalStackValEnforcer = do
-    flgs <- ask
-    s <- getStack
-    let topStack = if null s then [] else head s
-    if not $ MINIMALDATA `elem` flgs || null topStack
-        then return ()
-        else case checkMinimalNumRep topStack  of
-            True -> return ()
-            False -> programError $ "Non-minimal stack value: " ++ (show topStack)
-
--- | Checks if a stack value is the minimal numeric representation of
--- the integer to which it decoes.  Based on CScriptNum from Bitcoin
--- Core.
-checkMinimalNumRep :: StackValue -> Bool
-checkMinimalNumRep [] = True
-checkMinimalNumRep s =
-    let msb = last s
-        l = length s in
-    if
-         -- If the MSB except sign bit is zero, then nonMinimal
-         ( msb .&. 0x7f == 0 )
-         -- With the exception of when a new byte is forced by a filled last bit
-      && ( l <= 1 || ( s !! (l-2) ) .&. 0x80 == 0 )
-    then False
-    else True
-
-nullDummyEnforcer :: StackOperation ()
-nullDummyEnforcer = do
-    flgs <- ask
-    topStack <- ( getStack >>= headOrError )
-    if ( NULLDUMMY `elem` flgs ) && ( not . null $ topStack )
-        then programError $ "Non-null dummy stack in multi-sig"
-        else return ()
-    where
-        headOrError s = if null s
-          then programError "Empty stack where dummy op should be."
-          else return ( head s )
-
---------------------------------------------------------------------------------
--- | Based on the IfStack, returns whether the script is within an
--- evaluating if-branch.
-getExec :: Program Bool
-getExec = and <$> getCond
-
--- | Converts a `ScriptOp` to a ProgramData monad.
-conditionalEval :: ScriptOp -> Program ()
-conditionalEval scrpOp = do
-   -- lift $ checkOpEnabled scrpOp
-   lift $ checkPushData scrpOp
-
-   e  <- getExec
-   eval' e scrpOp
-
-   when (countOp scrpOp) $ lift $ join $ incrementOpCount <$> opCount <$> get
-
-   lift checkStackSize
-
-   where
-     eval' :: Bool -> ScriptOp -> Program ()
-
-     eval' True  OP_IF      = lift popStack >>= pushCond . decodeBool
-     eval' True  OP_NOTIF   = lift popStack >>= pushCond . not . decodeBool
-     eval' True  OP_ELSE    = flipCond
-     eval' True  OP_ENDIF   = void popCond
-     eval' True  op = lift $ eval op
-
-     eval' False OP_IF    = pushCond False
-     eval' False OP_NOTIF = pushCond False
-     eval' False OP_ELSE  = flipCond
-     eval' False OP_ENDIF = void popCond
-     eval' False OP_CODESEPARATOR = lift $ eval OP_CODESEPARATOR
-     eval' False OP_VER = return ()
-     eval' False op | isDisabled op = lift $ disabled op
-                    | otherwise = return ()
-
--- | Builds a Script evaluation monad.
-evalOps :: [ ScriptOp ] -> Program ()
-evalOps ops = do mapM_ conditionalEval ops
-                 cond <- getCond
-                 unless (null cond) (lift $ programError "ifStack not empty")
-
-
-checkPushOnly :: [ ScriptOp ] -> Program ()
-checkPushOnly ops
-      | not (all checkPushOp ops) = lift $ programError "only push ops allowed"
-      | otherwise = return ()
-      where checkPushOp op = case constValue op of
-                                  Just _ -> True
-                                  Nothing -> False
-
-checkStack :: Stack -> Bool
-checkStack (x:_) = decodeBool x
-checkStack []  = False
-
-
-isPayToScriptHash :: [ ScriptOp ] -> [ Flag ]  -> Bool
-isPayToScriptHash [OP_HASH160, OP_PUSHDATA bytes OPCODE, OP_EQUAL] flgs
-                    = ( P2SH `elem` flgs ) && ( BS.length bytes == 20 )
-isPayToScriptHash _ _ = False
-
-stackToScriptOps :: StackValue -> [ ScriptOp ]
-stackToScriptOps sv = case decode $ BS.pack sv of
-    Left _  -> []  -- Maybe should propogate the error some how
-    Right s -> scriptOps s
-
--- exported functions
-
-execScript :: Script -- ^ scriptSig ( redeemScript )
-           -> Script -- ^ scriptPubKey
-           -> SigCheck -- ^ signature verification Function
-           -> [ Flag ] -- ^ Evaluation flags
-           -> Either EvalError ProgramData
-execScript scriptSig scriptPubKey sigCheckFcn flags =
-  let sigOps = scriptOps scriptSig
-      pubKeyOps = scriptOps scriptPubKey
-      initData = ProgramData {
-        stack = [],
-        altStack = [],
-        hashOps = pubKeyOps,
-        sigCheck = sigCheckFcn,
-        opCount = 0
-      }
-
-
-      checkSig | isPayToScriptHash pubKeyOps flags = checkPushOnly sigOps
-               | SIGPUSHONLY `elem` flags = checkPushOnly sigOps
-               | otherwise = return ()
-
-      checkKey | BS.length (encode scriptPubKey) > fromIntegral maxScriptSize
-                 = lift $ programError "pubKey > maxScriptSize"
-               | otherwise = return ()
-
-
-      redeemEval = checkSig >> evalOps sigOps >> lift (stack <$> get)
-      pubKeyEval = checkKey >> evalOps pubKeyOps >> lift get
-
-      in do s <- evalProgram redeemEval [] initData flags
-            p <- evalProgram pubKeyEval [] initData { stack = s } flags
-            if ( not . null $ s )
-                   && ( isPayToScriptHash pubKeyOps flags )
-                   && ( checkStack . runStack $ p )
-              then evalProgram (evalP2SH s) [] initData { stack = drop 1 s,
-                      hashOps = stackToScriptOps $ head s } flags
-              else return p
-
-
--- | Evaluates a P2SH style script from its serialization in the stack
-evalP2SH :: Stack -> Program ProgramData
-evalP2SH [] = lift $ programError "PayToScriptHash: no script on stack"
-evalP2SH (sv:_) = evalOps (stackToScriptOps sv) >> lift get
-
-evalScript :: Script -> Script -> SigCheck -> [ Flag ] -> Bool
-evalScript scriptSig scriptPubKey sigCheckFcn flags =
-              case execScript scriptSig scriptPubKey sigCheckFcn flags of
-                  Left _ -> False
-                  Right p -> checkStack . runStack $ p
-
-runStack :: ProgramData -> Stack
-runStack = stack
-
--- | A wrapper around 'verifySig' which handles grabbing the hash type
-verifySigWithType :: Tx -> Int -> [ ScriptOp ] -> TxSignature -> PubKey -> Bool
-verifySigWithType tx i outOps txSig pubKey =
-  let outScript = Script outOps
-      h = txSigHash tx outScript i ( sigHashType txSig ) in
-  verifySig h ( txSignature txSig ) pubKey
-
--- | Uses `evalScript` to check that the input script of a spending
--- transaction satisfies the output script.
-verifySpend :: Tx     -- ^ The spending transaction
-            -> Int    -- ^ The input index
-            -> Script -- ^ The output script we are spending
-            -> [ Flag ] -- ^ Evaluation flags
-            -> Bool
-verifySpend tx i outscript flags =
-  let scriptSig = either (const err) id . decode . scriptInput $ txIn tx !! i
-      verifyFcn = verifySigWithType tx i
-      err       = error "Could not decode scriptInput in verifySpend"
-  in evalScript scriptSig outscript verifyFcn flags
-
diff --git a/Network/Haskoin/Script/Parser.hs b/Network/Haskoin/Script/Parser.hs
deleted file mode 100644
--- a/Network/Haskoin/Script/Parser.hs
+++ /dev/null
@@ -1,335 +0,0 @@
-module Network.Haskoin.Script.Parser
-( ScriptOutput(..)
-, ScriptInput(..)
-, SimpleInput(..)
-, RedeemScript
-, scriptAddr
-, outputAddress
-, inputAddress
-, encodeInput
-, encodeInputBS
-, decodeInput
-, decodeInputBS
-, encodeOutput
-, encodeOutputBS
-, decodeOutput
-, decodeOutputBS
-, sortMulSig
-, intToScriptOp
-, scriptOpToInt
-, isPayPK
-, isPayPKHash
-, isPayMulSig
-, isPayScriptHash
-, isSpendPK
-, isSpendPKHash
-, isSpendMulSig
-, isScriptHashInput
-, isDataCarrier
-) where
-
-import           Control.Applicative            ((<|>))
-import           Control.DeepSeq                (NFData, rnf)
-import           Control.Monad                  (guard, liftM2, (<=<))
-import           Data.Aeson                     (FromJSON, ToJSON,
-                                                 Value (String), parseJSON,
-                                                 toJSON, withText)
-import           Data.ByteString                (ByteString)
-import qualified Data.ByteString                as BS (head, singleton)
-import           Data.Foldable                  (foldrM)
-import           Data.List                      (sortBy)
-import           Data.Serialize                 (encode, decode)
-import           Data.String.Conversions        (cs)
-import           Network.Haskoin.Crypto.Base58
-import           Network.Haskoin.Crypto.Hash
-import           Network.Haskoin.Crypto.Keys
-import           Network.Haskoin.Script.SigHash
-import           Network.Haskoin.Script.Types
-import           Network.Haskoin.Util
-
--- | Data type describing standard transaction output scripts. Output scripts
--- provide the conditions that must be fulfilled for someone to spend the
--- output coins.
-data ScriptOutput =
-      -- | Pay to a public key.
-      PayPK         { getOutputPubKey   :: !PubKey }
-      -- | Pay to a public key hash.
-    | PayPKHash     { getOutputAddress  :: !Address }
-      -- | Pay to multiple public keys.
-    | PayMulSig     { getOutputMulSigKeys     :: ![PubKey]
-                    , getOutputMulSigRequired :: !Int
-                    }
-      -- | Pay to a script hash.
-    | PayScriptHash { getOutputAddress  :: !Address }
-      -- | Provably unspendable data carrier.
-    | DataCarrier { getOutputData :: !ByteString }
-    deriving (Eq, Show, Read)
-
-instance FromJSON ScriptOutput where
-    parseJSON = withText "scriptoutput" $ \t -> either fail return $
-        maybeToEither "scriptoutput not hex" (decodeHex $ cs t) >>=
-        decodeOutputBS
-
-instance ToJSON ScriptOutput where
-    toJSON = String . cs . encodeHex . encodeOutputBS
-
-instance NFData ScriptOutput where
-    rnf (PayPK k) = rnf k
-    rnf (PayPKHash a) = rnf a
-    rnf (PayMulSig k r) = rnf k `seq` rnf r
-    rnf (PayScriptHash a) = rnf a
-    rnf (DataCarrier a) = rnf a
-
--- | Returns True if the script is a pay to public key output.
-isPayPK :: ScriptOutput -> Bool
-isPayPK (PayPK _) = True
-isPayPK _ = False
-
--- | Returns True if the script is a pay to public key hash output.
-isPayPKHash :: ScriptOutput -> Bool
-isPayPKHash (PayPKHash _) = True
-isPayPKHash _ = False
-
--- | Returns True if the script is a pay to multiple public keys output.
-isPayMulSig :: ScriptOutput -> Bool
-isPayMulSig (PayMulSig _ _) = True
-isPayMulSig _ = False
-
--- | Returns true if the script is a pay to script hash output.
-isPayScriptHash :: ScriptOutput -> Bool
-isPayScriptHash (PayScriptHash _) = True
-isPayScriptHash _ = False
-
--- | Returns True if the script is an OP_RETURN "datacarrier" output
-isDataCarrier :: ScriptOutput -> Bool
-isDataCarrier (DataCarrier _) = True
-isDataCarrier _ = False
-
--- | Computes a script address from a script output. This address can be used
--- in a pay to script hash output.
-scriptAddr :: ScriptOutput -> Address
-scriptAddr = ScriptAddress . hash160 . getHash256 . hash256 . encodeOutputBS
-
--- | Sorts the public keys of a multisignature output in ascending order by
--- comparing their serialized representations. This feature allows for easier
--- multisignature account management as participants in a multisignature wallet
--- will blindly agree on an ordering of the public keys without having to
--- communicate.
-sortMulSig :: ScriptOutput -> ScriptOutput
-sortMulSig out = case out of
-    PayMulSig keys r -> PayMulSig (sortBy f keys) r
-    _ -> error "Can only call orderMulSig on PayMulSig scripts"
-  where
-    f a b = encode a `compare` encode b
-
--- | Computes a 'Script' from a 'ScriptOutput'. The 'Script' is a list of
--- 'ScriptOp' can can be used to build a 'Tx'.
-encodeOutput :: ScriptOutput -> Script
-encodeOutput s = Script $ case s of
-    -- Pay to PubKey
-    (PayPK k) -> [opPushData $ encode k, OP_CHECKSIG]
-    -- Pay to PubKey Hash Address
-    (PayPKHash a) -> case a of
-        (PubKeyAddress h) -> [ OP_DUP, OP_HASH160, opPushData $ encode h
-                             , OP_EQUALVERIFY, OP_CHECKSIG
-                             ]
-        (ScriptAddress _) ->
-            error "encodeOutput: ScriptAddress is invalid in PayPKHash"
-    -- Pay to MultiSig Keys
-    (PayMulSig ps r)
-      | r <= length ps ->
-        let opM = intToScriptOp r
-            opN = intToScriptOp $ length ps
-            keys = map (opPushData . encode) ps
-            in opM : keys ++ [opN, OP_CHECKMULTISIG]
-      | otherwise -> error "encodeOutput: PayMulSig r must be <= than pkeys"
-    -- Pay to Script Hash Address
-    (PayScriptHash a) -> case a of
-        (ScriptAddress h) -> [ OP_HASH160
-                             , opPushData $ encode h, OP_EQUAL
-                             ]
-        (PubKeyAddress _) ->
-            error "encodeOutput: PubKeyAddress is invalid in PayScriptHash"
-    -- Provably unspendable output
-    (DataCarrier d) -> [OP_RETURN, opPushData d]
-
--- | Similar to 'encodeOutput' but encodes to a ByteString
-encodeOutputBS :: ScriptOutput -> ByteString
-encodeOutputBS = encode . encodeOutput
-
--- | Tries to decode a 'ScriptOutput' from a 'Script'. This can fail if the
--- script is not recognized as any of the standard output types.
-decodeOutput :: Script -> Either String ScriptOutput
-decodeOutput s = case scriptOps s of
-    -- Pay to PubKey
-    [OP_PUSHDATA bs _, OP_CHECKSIG] -> PayPK <$> decode bs
-    -- Pay to PubKey Hash
-    [OP_DUP, OP_HASH160, OP_PUSHDATA bs _, OP_EQUALVERIFY, OP_CHECKSIG] ->
-        (PayPKHash . PubKeyAddress) <$> decode bs
-    -- Pay to Script Hash
-    [OP_HASH160, OP_PUSHDATA bs _, OP_EQUAL] ->
-        (PayScriptHash . ScriptAddress) <$> decode bs
-    -- Provably unspendable data carrier output
-    [OP_RETURN, OP_PUSHDATA bs _] -> Right $ DataCarrier bs
-    -- Pay to MultiSig Keys
-    _ -> matchPayMulSig s
-
--- | Similar to 'decodeOutput' but decodes from a ByteString
-decodeOutputBS :: ByteString -> Either String ScriptOutput
-decodeOutputBS = decodeOutput <=< decode
-
--- Match [ OP_N, PubKey1, ..., PubKeyM, OP_M, OP_CHECKMULTISIG ]
-matchPayMulSig :: Script -> Either String ScriptOutput
-matchPayMulSig (Script ops) = case splitAt (length ops - 2) ops of
-    (m:xs,[n,OP_CHECKMULTISIG]) -> do
-        (intM,intN) <- liftM2 (,) (scriptOpToInt m) (scriptOpToInt n)
-        if intM <= intN && length xs == intN
-            then liftM2 PayMulSig (go xs) (return intM)
-            else Left "matchPayMulSig: Invalid M or N parameters"
-    _ -> Left "matchPayMulSig: script did not match output template"
-  where
-    go (OP_PUSHDATA bs _:xs) = liftM2 (:) (decode bs) (go xs)
-    go [] = return []
-    go  _ = Left "matchPayMulSig: invalid multisig opcode"
-
--- | Transforms integers [1 .. 16] to 'ScriptOp' [OP_1 .. OP_16]
-intToScriptOp :: Int -> ScriptOp
-intToScriptOp i
-    | i `elem` [1..16] = either (const err) id op
-    | otherwise = err
-  where
-    op  = decode $ BS.singleton $ fromIntegral $ i + 0x50
-    err = error $ "intToScriptOp: Invalid integer " ++ (show i)
-
--- | Decode 'ScriptOp' [OP_1 .. OP_16] to integers [1 .. 16]. This functions
--- fails for other values of 'ScriptOp'
-scriptOpToInt :: ScriptOp -> Either String Int
-scriptOpToInt s
-    | res `elem` [1..16] = return res
-    | otherwise          = Left $ "scriptOpToInt: invalid opcode " ++ (show s)
-  where
-    res = (fromIntegral $ BS.head $ encode s) - 0x50
-
--- | Get the address of a `ScriptOutput`
-outputAddress :: ScriptOutput -> Either String Address
-outputAddress s = case s of
-    PayPKHash a -> return a
-    PayScriptHash a -> return a
-    PayPK k -> return $ pubKeyAddr k
-    _ -> Left "outputAddress: bad output script type"
-
--- | Get the address of a `ScriptInput`
-inputAddress :: ScriptInput -> Either String Address
-inputAddress s = case s of
-    RegularInput (SpendPKHash _ key) -> return $ pubKeyAddr key
-    ScriptHashInput _ rdm -> return $ scriptAddr rdm
-    _ -> Left "inputAddress: bad input script type"
-
--- | Data type describing standard transaction input scripts. Input scripts
--- provide the signing data required to unlock the coins of the output they are
--- trying to spend.
-data SimpleInput
-      -- | Spend the coins of a PayPK output.
-    = SpendPK     { getInputSig :: !TxSignature }
-      -- | Spend the coins of a PayPKHash output.
-    | SpendPKHash { getInputSig :: !TxSignature
-                  , getInputKey :: !PubKey
-                  }
-      -- | Spend the coins of a PayMulSig output.
-    | SpendMulSig { getInputMulSigKeys :: ![TxSignature] }
-    deriving (Eq, Show, Read)
-
-instance NFData SimpleInput where
-    rnf (SpendPK i) = rnf i
-    rnf (SpendPKHash i k) = rnf i `seq` rnf k
-    rnf (SpendMulSig k) = rnf k
-
--- | Returns True if the input script is spending a public key.
-isSpendPK :: ScriptInput -> Bool
-isSpendPK (RegularInput (SpendPK _)) = True
-isSpendPK _ = False
-
--- | Returns True if the input script is spending a public key hash.
-isSpendPKHash :: ScriptInput -> Bool
-isSpendPKHash (RegularInput (SpendPKHash _ _)) = True
-isSpendPKHash _ = False
-
--- | Returns True if the input script is spending a multisignature output.
-isSpendMulSig :: ScriptInput -> Bool
-isSpendMulSig (RegularInput (SpendMulSig _)) = True
-isSpendMulSig _ = False
-
-isScriptHashInput :: ScriptInput -> Bool
-isScriptHashInput (ScriptHashInput _ _) = True
-isScriptHashInput _ = False
-
-type RedeemScript = ScriptOutput
-
-data ScriptInput
-    = RegularInput    { getRegularInput     :: SimpleInput }
-    | ScriptHashInput { getScriptHashInput  :: SimpleInput
-                      , getScriptHashRedeem :: RedeemScript
-                      }
-    deriving (Eq, Show, Read)
-
-instance NFData ScriptInput where
-    rnf (RegularInput i) = rnf i
-    rnf (ScriptHashInput i o) = rnf i `seq` rnf o
-
--- | Computes a 'Script' from a 'SimpleInput'. The 'Script' is a list of
--- 'ScriptOp' that can be used to build a 'Tx'.
-encodeSimpleInput :: SimpleInput -> Script
-encodeSimpleInput s = Script $ case s of
-    SpendPK ts       -> [ opPushData $ encodeSig ts ]
-    SpendPKHash ts p -> [ opPushData $ encodeSig ts
-                        , opPushData $ encode p
-                        ]
-    SpendMulSig ts   -> OP_0 : map (opPushData . encodeSig) ts
-
-decodeSimpleInput :: Script -> Either String SimpleInput
-decodeSimpleInput (Script ops) = maybeToEither errMsg $
-    matchPK ops <|> matchPKHash ops <|> matchMulSig ops
-  where
-    matchPK [OP_PUSHDATA bs _] = SpendPK <$> eitherToMaybe (decodeSig bs)
-    matchPK _ = Nothing
-    matchPKHash [OP_PUSHDATA sig _, OP_PUSHDATA pub _] =
-        liftM2 SpendPKHash (eitherToMaybe $ decodeSig sig) (decodeToMaybe pub)
-    matchPKHash _ = Nothing
-    matchMulSig (x:xs) = do
-        guard $ isPushOp x
-        SpendMulSig <$> foldrM f [] xs
-    matchMulSig _ = Nothing
-    f (OP_PUSHDATA bs _) acc =
-        liftM2 (:) (eitherToMaybe $ decodeSig bs) (Just acc)
-    f _ _ = Nothing
-    errMsg = "decodeInput: Could not decode script input"
-
-encodeInput :: ScriptInput -> Script
-encodeInput s = case s of
-    RegularInput ri -> encodeSimpleInput ri
-    ScriptHashInput i o -> Script $
-        (scriptOps $ encodeSimpleInput i) ++ [opPushData $ encodeOutputBS o]
-
--- | Similar to 'encodeInput' but encodes to a ByteString
-encodeInputBS :: ScriptInput -> ByteString
-encodeInputBS = encode . encodeInput
-
--- | Decodes a 'ScriptInput' from a 'Script'. This function fails if the
--- script can not be parsed as a standard script input.
-decodeInput :: Script -> Either String ScriptInput
-decodeInput s@(Script ops) = maybeToEither errMsg $
-    matchSimpleInput <|> matchPayScriptHash
-  where
-    matchSimpleInput = RegularInput <$> (eitherToMaybe $ decodeSimpleInput s)
-    matchPayScriptHash = case splitAt (length (scriptOps s) - 1) ops of
-        (is, [OP_PUSHDATA bs _]) -> do
-            rdm <- eitherToMaybe $ decodeOutputBS bs
-            inp <- eitherToMaybe $ decodeSimpleInput $ Script is
-            return $ ScriptHashInput inp rdm
-        _ -> Nothing
-    errMsg = "decodeInput: Could not decode script input"
-
--- | Similar to 'decodeInput' but decodes from a ByteString
-decodeInputBS :: ByteString -> Either String ScriptInput
-decodeInputBS = decodeInput <=< decode
-
diff --git a/Network/Haskoin/Script/SigHash.hs b/Network/Haskoin/Script/SigHash.hs
deleted file mode 100644
--- a/Network/Haskoin/Script/SigHash.hs
+++ /dev/null
@@ -1,192 +0,0 @@
-module Network.Haskoin.Script.SigHash
-( SigHash(..)
-, encodeSigHash32
-, isSigAll
-, isSigNone
-, isSigSingle
-, isSigUnknown
-, txSigHash
-, TxSignature(..)
-, encodeSig
-, decodeSig
-, decodeCanonicalSig
-) where
-
-import           Control.DeepSeq                   (NFData, rnf)
-import           Control.Monad                     (liftM2, mzero, (<=<))
-import           Data.Aeson                        (FromJSON, ToJSON,
-                                                    Value (String), parseJSON,
-                                                    toJSON, withText)
-import           Data.Bits                         (clearBit, testBit)
-import           Data.ByteString                   (ByteString)
-import qualified Data.ByteString                   as BS (append, empty, init,
-                                                          last, length, pack,
-                                                          singleton, splitAt)
-import           Data.Maybe                        (fromMaybe)
-import           Data.Serialize                    (Serialize, decode, encode,
-                                                    get, getWord8, put,
-                                                    putWord8, runPut)
-import           Data.String.Conversions           (cs)
-import           Data.Word                         (Word8)
-import           Network.Haskoin.Crypto.ECDSA
-import           Network.Haskoin.Crypto.Hash
-import           Network.Haskoin.Script.Types
-import           Network.Haskoin.Transaction.Types
-import           Network.Haskoin.Util
-
--- | Data type representing the different ways a transaction can be signed.
--- When producing a signature, a hash of the transaction is used as the message
--- to be signed. The 'SigHash' parameter controls which parts of the
--- transaction are used or ignored to produce the transaction hash. The idea is
--- that if some part of a transaction is not used to produce the transaction
--- hash, then you can change that part of the transaction after producing a
--- signature without invalidating that signature.
---
--- If the anyoneCanPay flag is True, then only the current input is signed.
--- Otherwise, all of the inputs of a transaction are signed. The default value
--- for anyoneCanPay is False.
-data SigHash
-    -- | Sign all of the outputs of a transaction (This is the default value).
-    -- Changing any of the outputs of the transaction will invalidate the
-    -- signature.
-    = SigAll     { anyoneCanPay :: !Bool }
-    -- | Sign none of the outputs of a transaction. This allows anyone to
-    -- change any of the outputs of the transaction.
-    | SigNone    { anyoneCanPay :: !Bool }
-    -- | Sign only the output corresponding the the current transaction input.
-    -- You care about your own output in the transaction but you don't
-    -- care about any of the other outputs.
-    | SigSingle  { anyoneCanPay :: !Bool }
-    -- | Unrecognized sighash types will decode to SigUnknown.
-    | SigUnknown { anyoneCanPay :: !Bool
-                 , getSigCode   :: !Word8
-                 }
-    deriving (Eq, Show, Read)
-
-instance NFData SigHash where
-    rnf (SigAll a) = rnf a
-    rnf (SigNone a) = rnf a
-    rnf (SigSingle a) = rnf a
-    rnf (SigUnknown a c) = rnf a `seq` rnf c
-
--- | Returns True if the 'SigHash' has the value SigAll.
-isSigAll :: SigHash -> Bool
-isSigAll sh = case sh of
-    SigAll _ -> True
-    _ -> False
-
--- | Returns True if the 'SigHash' has the value SigNone.
-isSigNone :: SigHash -> Bool
-isSigNone sh = case sh of
-    SigNone _ -> True
-    _ -> False
-
--- | Returns True if the 'SigHash' has the value SigSingle.
-isSigSingle :: SigHash -> Bool
-isSigSingle sh = case sh of
-    SigSingle _ -> True
-    _ -> False
-
--- | Returns True if the 'SigHash' has the value SigUnknown.
-isSigUnknown :: SigHash -> Bool
-isSigUnknown sh = case sh of
-    SigUnknown _ _ -> True
-    _ -> False
-
-instance Serialize SigHash where
-
-    get = getWord8 >>= \w ->
-        let acp = testBit w 7
-            in return $ case clearBit w 7 of
-                1 -> SigAll acp
-                2 -> SigNone acp
-                3 -> SigSingle acp
-                _ -> SigUnknown acp w
-
-    put sh = putWord8 $ case sh of
-        SigAll acp -> if acp then 0x81 else 0x01
-        SigNone acp -> if acp then 0x82 else 0x02
-        SigSingle acp -> if acp then 0x83 else 0x03
-        SigUnknown _ w -> w
-
-instance ToJSON SigHash where
-    toJSON = String . cs . encodeHex . encode
-
-instance FromJSON SigHash where
-    parseJSON = withText "sighash" $
-        maybe mzero return . (decodeToMaybe <=< decodeHex) . cs
-
--- | Encodes a 'SigHash' to a 32 bit-long bytestring.
-encodeSigHash32 :: SigHash -> ByteString
-encodeSigHash32 sh = encode sh `BS.append` BS.pack [0,0,0]
-
--- | Computes the hash that will be used for signing a transaction.
-txSigHash :: Tx      -- ^ Transaction to sign.
-          -> Script  -- ^ Output script that is being spent.
-          -> Int     -- ^ Index of the input that is being signed.
-          -> SigHash -- ^ What parts of the transaction should be signed.
-          -> Hash256 -- ^ Result hash to be signed.
-txSigHash tx out i sh = do
-    let newIn = buildInputs (txIn tx) out i sh
-    -- When SigSingle and input index > outputs, then sign integer 1
-    fromMaybe one $ do
-        newOut <- buildOutputs (txOut tx) i sh
-        let newTx = createTx (txVersion tx) newIn newOut (txLockTime tx)
-        return $ doubleHash256 $ encode newTx `BS.append` encodeSigHash32 sh
-  where
-    one = "0100000000000000000000000000000000000000000000000000000000000000"
-
--- Builds transaction inputs for computing SigHashes
-buildInputs :: [TxIn] -> Script -> Int -> SigHash -> [TxIn]
-buildInputs txins out i sh
-    | anyoneCanPay sh   = (txins !! i) { scriptInput = encode out } : []
-    | isSigAll sh || isSigUnknown sh = single
-    | otherwise         = map noSeq $ zip single [0..]
-  where
-    empty  = map (\ti -> ti{ scriptInput = BS.empty }) txins
-    single = updateIndex i empty $ \ti -> ti{ scriptInput = encode out }
-    noSeq (ti,j) = if i == j then ti else ti{ txInSequence = 0 }
-
--- Build transaction outputs for computing SigHashes
-buildOutputs :: [TxOut] -> Int -> SigHash -> Maybe [TxOut]
-buildOutputs txos i sh
-    | isSigAll sh || isSigUnknown sh = return txos
-    | isSigNone sh = return []
-    | i >= length txos = Nothing
-    | otherwise = return $ buffer ++ [txos !! i]
-  where
-    buffer = replicate i $ TxOut (-1) BS.empty
-
--- | Data type representing a 'Signature' together with a 'SigHash'. The
--- 'SigHash' is serialized as one byte at the end of a regular ECDSA
--- 'Signature'. All signatures in transaction inputs are of type 'TxSignature'.
-data TxSignature = TxSignature
-    { txSignature :: !Signature
-    , sigHashType :: !SigHash
-    } deriving (Eq, Show, Read)
-
-instance NFData TxSignature where
-    rnf (TxSignature s h) = rnf s `seq` rnf h
-
--- | Serialize a 'TxSignature' to a ByteString.
-encodeSig :: TxSignature -> ByteString
-encodeSig (TxSignature sig sh) = runPut $ put sig >> put sh
-
--- | Decode a 'TxSignature' from a ByteString.
-decodeSig :: ByteString -> Either String TxSignature
-decodeSig bs = do
-    let (h, l) = BS.splitAt (BS.length bs - 1) bs
-    liftM2 TxSignature (decode h) (decode l)
-
-decodeCanonicalSig :: ByteString -> Either String TxSignature
-decodeCanonicalSig bs
-    | hashtype < 1 || hashtype > 3 =
-        Left "Non-canonical signature: unknown hashtype byte"
-    | otherwise =
-        case decodeStrictSig $ BS.init bs of
-            Just sig ->
-                TxSignature sig <$> decode (BS.singleton $ BS.last bs)
-            Nothing  ->
-                Left "Non-canonical signature: could not parse signature"
-  where
-    hashtype = clearBit (BS.last bs) 7
diff --git a/Network/Haskoin/Script/Types.hs b/Network/Haskoin/Script/Types.hs
deleted file mode 100644
--- a/Network/Haskoin/Script/Types.hs
+++ /dev/null
@@ -1,541 +0,0 @@
-module Network.Haskoin.Script.Types
-( ScriptOp(..)
-, Script(..)
-, PushDataType(..)
-, isPushOp
-, opPushData
-) where
-
-import Control.DeepSeq (NFData, rnf)
-import Control.Monad (unless, forM_)
-
-import Data.Word (Word8)
-import Data.Serialize (Serialize, get, put)
-import Data.Serialize.Get
-    ( isEmpty
-    , getWord8
-    , getWord16le
-    , getWord32le
-    , getByteString
-    )
-import Data.Serialize.Put
-    ( putWord8
-    , putWord16le
-    , putWord32le
-    , putByteString
-    )
-import qualified Data.ByteString as BS
-    ( ByteString
-    , length
-    )
-
--- | Data type representing a transaction script. Scripts are defined as lists
--- of script operators 'ScriptOp'. Scripts are used to:
---
--- * Define the spending conditions in the output of a transaction
---
--- * Provide the spending signatures in the input of a transaction
-data Script =
-    Script {
-             -- | List of script operators defining this script
-             scriptOps :: ![ScriptOp]
-           }
-    deriving (Eq, Show, Read)
-
-instance NFData Script where
-    rnf (Script o) = rnf o
-
-instance Serialize Script where
-    get =
-        Script <$> getScriptOps
-      where
-        getScriptOps = do
-            empty <- isEmpty
-            if empty
-                then return []
-                else (:) <$> get <*> getScriptOps
-
-    put (Script ops) = forM_ ops put
-
--- | Data type representing the type of an OP_PUSHDATA opcode.
-data PushDataType
-    =
-      -- | The next opcode bytes is data to be pushed onto the stack
-      OPCODE
-      -- | The next byte contains the number of bytes to be pushed onto
-      -- the stack
-    | OPDATA1
-      -- | The next two bytes contains the number of bytes to be pushed onto
-      -- the stack
-    | OPDATA2
-      -- | The next four bytes contains the number of bytes to be pushed onto
-      -- the stack
-    | OPDATA4
-    deriving (Show, Read, Eq)
-
-instance NFData PushDataType where rnf x = seq x ()
-
--- | Data type representing all of the operators allowed inside a 'Script'.
-data ScriptOp
-      -- Pushing Data
-    = OP_PUSHDATA !BS.ByteString !PushDataType
-    | OP_0
-    | OP_1NEGATE
-    | OP_RESERVED
-    | OP_1  | OP_2  | OP_3  | OP_4
-    | OP_5  | OP_6  | OP_7  | OP_8
-    | OP_9  | OP_10 | OP_11 | OP_12
-    | OP_13 | OP_14 | OP_15 | OP_16
-
-      -- Flow control
-    | OP_NOP
-    | OP_VER        -- reserved
-    | OP_IF
-    | OP_NOTIF
-    | OP_VERIF      -- resreved
-    | OP_VERNOTIF   -- reserved
-    | OP_ELSE
-    | OP_ENDIF
-    | OP_VERIFY
-    | OP_RETURN
-
-      -- Stack operations
-    | OP_TOALTSTACK
-    | OP_FROMALTSTACK
-    | OP_IFDUP
-    | OP_DEPTH
-    | OP_DROP
-    | OP_DUP
-    | OP_NIP
-    | OP_OVER
-    | OP_PICK
-    | OP_ROLL
-    | OP_ROT
-    | OP_SWAP
-    | OP_TUCK
-    | OP_2DROP
-    | OP_2DUP
-    | OP_3DUP
-    | OP_2OVER
-    | OP_2ROT
-    | OP_2SWAP
-
-      -- Splice
-    | OP_CAT
-    | OP_SUBSTR
-    | OP_LEFT
-    | OP_RIGHT
-    | OP_SIZE
-
-      -- Bitwise logic
-    | OP_INVERT
-    | OP_AND
-    | OP_OR
-    | OP_XOR
-    | OP_EQUAL
-    | OP_EQUALVERIFY
-    | OP_RESERVED1
-    | OP_RESERVED2
-
-      -- Arithmetic
-    | OP_1ADD
-    | OP_1SUB
-    | OP_2MUL
-    | OP_2DIV
-    | OP_NEGATE
-    | OP_ABS
-    | OP_NOT
-    | OP_0NOTEQUAL
-    | OP_ADD
-    | OP_SUB
-    | OP_MUL
-    | OP_DIV
-    | OP_MOD
-    | OP_LSHIFT
-    | OP_RSHIFT
-    | OP_BOOLAND
-    | OP_BOOLOR
-    | OP_NUMEQUAL
-    | OP_NUMEQUALVERIFY
-    | OP_NUMNOTEQUAL
-    | OP_LESSTHAN
-    | OP_GREATERTHAN
-    | OP_LESSTHANOREQUAL
-    | OP_GREATERTHANOREQUAL
-    | OP_MIN
-    | OP_MAX
-    | OP_WITHIN
-
-      -- Crypto
-    | OP_RIPEMD160
-    | OP_SHA1
-    | OP_SHA256
-    | OP_HASH160
-    | OP_HASH256
-    | OP_CODESEPARATOR
-    | OP_CHECKSIG
-    | OP_CHECKSIGVERIFY
-    | OP_CHECKMULTISIG
-    | OP_CHECKMULTISIGVERIFY
-
-      -- Expansion
-    | OP_NOP1 | OP_NOP2 | OP_NOP3 | OP_NOP4 | OP_NOP5
-    | OP_NOP6 | OP_NOP7 | OP_NOP8 | OP_NOP9 | OP_NOP10
-
-
-      -- Other
-    | OP_PUBKEYHASH
-    | OP_PUBKEY
-    | OP_INVALIDOPCODE !Word8
-
-        deriving (Show, Read, Eq)
-
-
-instance NFData ScriptOp where
-    rnf (OP_PUSHDATA b t) = rnf b `seq` rnf t
-    rnf (OP_INVALIDOPCODE c) = rnf c
-    rnf x = x `seq` ()
-
-
-instance Serialize ScriptOp where
-
-    get = go =<< (fromIntegral <$> getWord8)
-      where
-        go op
-            | op == 0x00 = return $ OP_0
-            | op <= 0x4b = do
-                payload <- getByteString (fromIntegral op)
-                return $ OP_PUSHDATA payload OPCODE
-            | op == 0x4c = do
-                len  <- getWord8
-                payload <- getByteString (fromIntegral len)
-                return $ OP_PUSHDATA payload OPDATA1
-            | op == 0x4d = do
-                len  <- getWord16le
-                payload <- getByteString (fromIntegral len)
-                return $ OP_PUSHDATA payload OPDATA2
-            | op == 0x4e = do
-                len  <- getWord32le
-                payload <- getByteString (fromIntegral len)
-                return $ OP_PUSHDATA payload OPDATA4
-
-            | op == 0x4f = return $ OP_1NEGATE
-            | op == 0x50 = return $ OP_RESERVED
-            | op == 0x51 = return $ OP_1
-            | op == 0x52 = return $ OP_2
-            | op == 0x53 = return $ OP_3
-            | op == 0x54 = return $ OP_4
-            | op == 0x55 = return $ OP_5
-            | op == 0x56 = return $ OP_6
-            | op == 0x57 = return $ OP_7
-            | op == 0x58 = return $ OP_8
-            | op == 0x59 = return $ OP_9
-            | op == 0x5a = return $ OP_10
-            | op == 0x5b = return $ OP_11
-            | op == 0x5c = return $ OP_12
-            | op == 0x5d = return $ OP_13
-            | op == 0x5e = return $ OP_14
-            | op == 0x5f = return $ OP_15
-            | op == 0x60 = return $ OP_16
-            -- Flow control
-            | op == 0x61 = return $ OP_NOP
-            | op == 0x62 = return $ OP_VER        -- reserved
-            | op == 0x63 = return $ OP_IF
-            | op == 0x64 = return $ OP_NOTIF
-            | op == 0x65 = return $ OP_VERIF      -- reserved
-            | op == 0x66 = return $ OP_VERNOTIF   -- reserved
-            | op == 0x67 = return $ OP_ELSE
-            | op == 0x68 = return $ OP_ENDIF
-            | op == 0x69 = return $ OP_VERIFY
-            | op == 0x6a = return $ OP_RETURN
-
-            -- Stack
-            | op == 0x6b = return $ OP_TOALTSTACK
-            | op == 0x6c = return $ OP_FROMALTSTACK
-            | op == 0x6d = return $ OP_2DROP
-            | op == 0x6e = return $ OP_2DUP
-            | op == 0x6f = return $ OP_3DUP
-            | op == 0x70 = return $ OP_2OVER
-            | op == 0x71 = return $ OP_2ROT
-            | op == 0x72 = return $ OP_2SWAP
-            | op == 0x73 = return $ OP_IFDUP
-            | op == 0x74 = return $ OP_DEPTH
-            | op == 0x75 = return $ OP_DROP
-            | op == 0x76 = return $ OP_DUP
-            | op == 0x77 = return $ OP_NIP
-            | op == 0x78 = return $ OP_OVER
-            | op == 0x79 = return $ OP_PICK
-            | op == 0x7a = return $ OP_ROLL
-            | op == 0x7b = return $ OP_ROT
-            | op == 0x7c = return $ OP_SWAP
-            | op == 0x7d = return $ OP_TUCK
-
-            -- Splice
-            | op == 0x7e = return $ OP_CAT
-            | op == 0x7f = return $ OP_SUBSTR
-            | op == 0x80 = return $ OP_LEFT
-            | op == 0x81 = return $ OP_RIGHT
-            | op == 0x82 = return $ OP_SIZE
-
-            -- Bitwise logic
-            | op == 0x83 = return $ OP_INVERT
-            | op == 0x84 = return $ OP_AND
-            | op == 0x85 = return $ OP_OR
-            | op == 0x86 = return $ OP_XOR
-            | op == 0x87 = return $ OP_EQUAL
-            | op == 0x88 = return $ OP_EQUALVERIFY
-            | op == 0x89 = return $ OP_RESERVED1
-            | op == 0x8a = return $ OP_RESERVED2
-
-            -- Arithmetic
-            | op == 0x8b = return $ OP_1ADD
-            | op == 0x8c = return $ OP_1SUB
-            | op == 0x8d = return $ OP_2MUL
-            | op == 0x8e = return $ OP_2DIV
-            | op == 0x8f = return $ OP_NEGATE
-            | op == 0x90 = return $ OP_ABS
-            | op == 0x91 = return $ OP_NOT
-            | op == 0x92 = return $ OP_0NOTEQUAL
-            | op == 0x93 = return $ OP_ADD
-            | op == 0x94 = return $ OP_SUB
-            | op == 0x95 = return $ OP_MUL
-            | op == 0x96 = return $ OP_DIV
-            | op == 0x97 = return $ OP_MOD
-            | op == 0x98 = return $ OP_LSHIFT
-            | op == 0x99 = return $ OP_RSHIFT
-            | op == 0x9a = return $ OP_BOOLAND
-            | op == 0x9b = return $ OP_BOOLOR
-            | op == 0x9c = return $ OP_NUMEQUAL
-            | op == 0x9d = return $ OP_NUMEQUALVERIFY
-            | op == 0x9e = return $ OP_NUMNOTEQUAL
-            | op == 0x9f = return $ OP_LESSTHAN
-            | op == 0xa0 = return $ OP_GREATERTHAN
-            | op == 0xa1 = return $ OP_LESSTHANOREQUAL
-            | op == 0xa2 = return $ OP_GREATERTHANOREQUAL
-            | op == 0xa3 = return $ OP_MIN
-            | op == 0xa4 = return $ OP_MAX
-            | op == 0xa5 = return $ OP_WITHIN
-
-            -- Crypto
-            | op == 0xa6 = return $ OP_RIPEMD160
-            | op == 0xa7 = return $ OP_SHA1
-            | op == 0xa8 = return $ OP_SHA256
-            | op == 0xa9 = return $ OP_HASH160
-            | op == 0xaa = return $ OP_HASH256
-            | op == 0xab = return $ OP_CODESEPARATOR
-            | op == 0xac = return $ OP_CHECKSIG
-            | op == 0xad = return $ OP_CHECKSIGVERIFY
-            | op == 0xae = return $ OP_CHECKMULTISIG
-            | op == 0xaf = return $ OP_CHECKMULTISIGVERIFY
-
-            -- More NOPs
-            | op == 0xb0 = return $ OP_NOP1
-            | op == 0xb1 = return $ OP_NOP2
-            | op == 0xb2 = return $ OP_NOP3
-            | op == 0xb3 = return $ OP_NOP4
-            | op == 0xb4 = return $ OP_NOP5
-            | op == 0xb5 = return $ OP_NOP6
-            | op == 0xb6 = return $ OP_NOP7
-            | op == 0xb7 = return $ OP_NOP8
-            | op == 0xb8 = return $ OP_NOP9
-            | op == 0xb9 = return $ OP_NOP10
-
-            -- Constants
-            | op == 0xfd = return $ OP_PUBKEYHASH
-            | op == 0xfe = return $ OP_PUBKEY
-
-            | otherwise = return $ OP_INVALIDOPCODE op
-
-    put op = case op of
-
-        (OP_PUSHDATA payload optype)-> do
-            let len = BS.length payload
-            case optype of
-                OPCODE -> do
-                    unless (len <= 0x4b) $ fail
-                        "OP_PUSHDATA OPCODE: Payload size too big"
-                    putWord8 $ fromIntegral len
-                OPDATA1 -> do
-                    unless (len <= 0xff) $ fail
-                        "OP_PUSHDATA OPDATA1: Payload size too big"
-                    putWord8 0x4c
-                    putWord8 $ fromIntegral len
-                OPDATA2 -> do
-                    unless (len <= 0xffff) $ fail
-                        "OP_PUSHDATA OPDATA2: Payload size too big"
-                    putWord8 0x4d
-                    putWord16le $ fromIntegral len
-                OPDATA4 -> do
-                    unless (len <= 0x7fffffff) $ fail
-                        "OP_PUSHDATA OPDATA4: Payload size too big"
-                    putWord8 0x4e
-                    putWord32le $ fromIntegral len
-            putByteString payload
-
-        -- Constants
-        OP_0                 -> putWord8 0x00
-        OP_1NEGATE           -> putWord8 0x4f
-        OP_RESERVED          -> putWord8 0x50
-        OP_1                 -> putWord8 0x51
-        OP_2                 -> putWord8 0x52
-        OP_3                 -> putWord8 0x53
-        OP_4                 -> putWord8 0x54
-        OP_5                 -> putWord8 0x55
-        OP_6                 -> putWord8 0x56
-        OP_7                 -> putWord8 0x57
-        OP_8                 -> putWord8 0x58
-        OP_9                 -> putWord8 0x59
-        OP_10                -> putWord8 0x5a
-        OP_11                -> putWord8 0x5b
-        OP_12                -> putWord8 0x5c
-        OP_13                -> putWord8 0x5d
-        OP_14                -> putWord8 0x5e
-        OP_15                -> putWord8 0x5f
-        OP_16                -> putWord8 0x60
-
-        -- Crypto Constants
-        OP_PUBKEY            -> putWord8 0xfe
-        OP_PUBKEYHASH        -> putWord8 0xfd
-
-        -- Invalid Opcodes
-        (OP_INVALIDOPCODE x) -> putWord8 x
-
-        -- Flow Control
-        OP_NOP               -> putWord8 0x61
-        OP_VER               -> putWord8 0x62
-        OP_IF                -> putWord8 0x63
-        OP_NOTIF             -> putWord8 0x64
-        OP_VERIF             -> putWord8 0x65
-        OP_VERNOTIF          -> putWord8 0x66
-        OP_ELSE              -> putWord8 0x67
-        OP_ENDIF             -> putWord8 0x68
-        OP_VERIFY            -> putWord8 0x69
-        OP_RETURN            -> putWord8 0x6a
-
-        -- Stack Operations
-        OP_TOALTSTACK        -> putWord8 0x6b
-        OP_FROMALTSTACK      -> putWord8 0x6c
-        OP_2DROP             -> putWord8 0x6d
-        OP_2DUP              -> putWord8 0x6e
-        OP_3DUP              -> putWord8 0x6f
-        OP_2OVER             -> putWord8 0x70
-        OP_2ROT              -> putWord8 0x71
-        OP_2SWAP             -> putWord8 0x72
-        OP_IFDUP             -> putWord8 0x73
-        OP_DEPTH             -> putWord8 0x74
-        OP_DROP              -> putWord8 0x75
-        OP_DUP               -> putWord8 0x76
-        OP_NIP               -> putWord8 0x77
-        OP_OVER              -> putWord8 0x78
-        OP_PICK              -> putWord8 0x79
-        OP_ROLL              -> putWord8 0x7a
-        OP_ROT               -> putWord8 0x7b
-        OP_SWAP              -> putWord8 0x7c
-        OP_TUCK              -> putWord8 0x7d
-
-        -- Splice
-        OP_CAT               -> putWord8 0x7e
-        OP_SUBSTR            -> putWord8 0x7f
-        OP_LEFT              -> putWord8 0x80
-        OP_RIGHT             -> putWord8 0x81
-        OP_SIZE              -> putWord8 0x82
-
-        -- Bitwise Logic
-        OP_INVERT            -> putWord8 0x83
-        OP_AND               -> putWord8 0x84
-        OP_OR                -> putWord8 0x85
-        OP_XOR               -> putWord8 0x86
-        OP_EQUAL             -> putWord8 0x87
-        OP_EQUALVERIFY       -> putWord8 0x88
-        OP_RESERVED1         -> putWord8 0x89
-        OP_RESERVED2         -> putWord8 0x8a
-
-        -- Arithmetic
-        OP_1ADD              -> putWord8 0x8b
-        OP_1SUB              -> putWord8 0x8c
-        OP_2MUL              -> putWord8 0x8d
-        OP_2DIV              -> putWord8 0x8e
-        OP_NEGATE            -> putWord8 0x8f
-        OP_ABS               -> putWord8 0x90
-        OP_NOT               -> putWord8 0x91
-        OP_0NOTEQUAL         -> putWord8 0x92
-        OP_ADD               -> putWord8 0x93
-        OP_SUB               -> putWord8 0x94
-        OP_MUL               -> putWord8 0x95
-        OP_DIV               -> putWord8 0x96
-        OP_MOD               -> putWord8 0x97
-        OP_LSHIFT            -> putWord8 0x98
-        OP_RSHIFT            -> putWord8 0x99
-        OP_BOOLAND           -> putWord8 0x9a
-        OP_BOOLOR            -> putWord8 0x9b
-        OP_NUMEQUAL          -> putWord8 0x9c
-        OP_NUMEQUALVERIFY    -> putWord8 0x9d
-        OP_NUMNOTEQUAL       -> putWord8 0x9e
-        OP_LESSTHAN          -> putWord8 0x9f
-        OP_GREATERTHAN       -> putWord8 0xa0
-        OP_LESSTHANOREQUAL   -> putWord8 0xa1
-        OP_GREATERTHANOREQUAL-> putWord8 0xa2
-        OP_MIN               -> putWord8 0xa3
-        OP_MAX               -> putWord8 0xa4
-        OP_WITHIN            -> putWord8 0xa5
-
-        -- Crypto
-        OP_RIPEMD160         -> putWord8 0xa6
-        OP_SHA1              -> putWord8 0xa7
-        OP_SHA256            -> putWord8 0xa8
-        OP_HASH160           -> putWord8 0xa9
-        OP_HASH256           -> putWord8 0xaa
-        OP_CODESEPARATOR     -> putWord8 0xab
-        OP_CHECKSIG          -> putWord8 0xac
-        OP_CHECKSIGVERIFY    -> putWord8 0xad
-        OP_CHECKMULTISIG     -> putWord8 0xae
-        OP_CHECKMULTISIGVERIFY -> putWord8 0xaf
-
-        -- More NOPs
-        OP_NOP1              -> putWord8 0xb0
-        OP_NOP2              -> putWord8 0xb1
-        OP_NOP3              -> putWord8 0xb2
-        OP_NOP4              -> putWord8 0xb3
-        OP_NOP5              -> putWord8 0xb4
-        OP_NOP6              -> putWord8 0xb5
-        OP_NOP7              -> putWord8 0xb6
-        OP_NOP8              -> putWord8 0xb7
-        OP_NOP9              -> putWord8 0xb8
-        OP_NOP10             -> putWord8 0xb9
-
-
--- | Check whether opcode is only data.
-isPushOp :: ScriptOp -> Bool
-isPushOp op = case op of
-    OP_PUSHDATA _ _ -> True
-    OP_0            -> True
-    OP_1NEGATE      -> True
-    OP_1            -> True
-    OP_2            -> True
-    OP_3            -> True
-    OP_4            -> True
-    OP_5            -> True
-    OP_6            -> True
-    OP_7            -> True
-    OP_8            -> True
-    OP_9            -> True
-    OP_10           -> True
-    OP_11           -> True
-    OP_12           -> True
-    OP_13           -> True
-    OP_14           -> True
-    OP_15           -> True
-    OP_16           -> True
-    _               -> False
-
--- | Optimally encode data using one of the 4 types of data pushing opcodes
-opPushData :: BS.ByteString -> ScriptOp
-opPushData bs
-    | len <= 0x4b       = OP_PUSHDATA bs OPCODE
-    | len <= 0xff       = OP_PUSHDATA bs OPDATA1
-    | len <= 0xffff     = OP_PUSHDATA bs OPDATA2
-    | len <= 0xffffffff = OP_PUSHDATA bs OPDATA4
-    | otherwise         = error "opPushData: payload size too big"
-  where
-    len = BS.length bs
-
diff --git a/Network/Haskoin/Test.hs b/Network/Haskoin/Test.hs
deleted file mode 100644
--- a/Network/Haskoin/Test.hs
+++ /dev/null
@@ -1,119 +0,0 @@
-{-|
-  This package provides test types for Network.Haskoin
--}
-module Network.Haskoin.Test
-(
-  -- * Util Arbitrary instances
-  ArbitraryByteString(..)
-, ArbitraryNotNullByteString(..)
-, ArbitraryUTCTime(..)
-, ArbitraryHash512(..)
-, ArbitraryHash256(..)
-, ArbitraryHash160(..)
-, ArbitraryCheckSum32(..)
-
-  -- * Crypto Arbitrary instances
-, ArbitraryPrvKey(..)
-, ArbitraryPrvKeyC(..)
-, ArbitraryPrvKeyU(..)
-, ArbitraryPubKey(..)
-, ArbitraryPubKeyC(..)
-, ArbitraryPubKeyU(..)
-, ArbitraryAddress(..)
-, ArbitraryPubKeyAddress(..)
-, ArbitraryScriptAddress(..)
-, ArbitrarySignature(..)
-, ArbitraryXPrvKey(..)
-, ArbitraryXPubKey(..)
-, ArbitraryHardPath(..)
-, ArbitrarySoftPath(..)
-, ArbitraryDerivPath(..)
-, ArbitraryParsedPath(..)
-
-  -- * Node Arbitrary instances
-, ArbitraryVarInt(..)
-, ArbitraryVarString(..)
-, ArbitraryNetworkAddress(..)
-, ArbitraryNetworkAddressTime(..)
-, ArbitraryInvType(..)
-, ArbitraryInvVector(..)
-, ArbitraryInv(..)
-, ArbitraryVersion(..)
-, ArbitraryAddr(..)
-, ArbitraryAlert(..)
-, ArbitraryReject(..)
-, ArbitraryRejectCode(..)
-, ArbitraryGetData(..)
-, ArbitraryNotFound(..)
-, ArbitraryPing(..)
-, ArbitraryPong(..)
-, ArbitraryBloomFlags(..)
-, ArbitraryBloomFilter(..)
-, ArbitraryFilterLoad(..)
-, ArbitraryFilterAdd(..)
-, ArbitraryMessageCommand(..)
-
-  -- * Message Arbitrary instances
-, ArbitraryMessageHeader(..)
-, ArbitraryMessage(..)
-
-  -- * Script Arbitrary instances
-, ArbitraryScriptOp(..)
-, ArbitraryScript(..)
-, ArbitraryIntScriptOp(..)
-, ArbitraryPushDataType(..)
-, ArbitraryTxSignature(..)
-, ArbitrarySigHash(..)
-, ArbitraryValidSigHash(..)
-, ArbitraryMSParam(..)
-, ArbitraryScriptOutput(..)
-, ArbitrarySimpleOutput(..)
-, ArbitraryPKOutput(..)
-, ArbitraryPKHashOutput(..)
-, ArbitraryMSOutput(..)
-, ArbitraryMSCOutput(..)
-, ArbitrarySHOutput(..)
-, ArbitraryScriptInput(..)
-, ArbitrarySimpleInput(..)
-, ArbitraryPKInput(..)
-, ArbitraryPKHashInput(..)
-, ArbitraryPKHashCInput(..)
-, ArbitraryMSInput(..)
-, ArbitrarySHInput(..)
-, ArbitraryMulSigSHCInput(..)
-
-  -- * Transaction Arbitrary instances
-, ArbitrarySatoshi(..)
-, ArbitraryTx(..)
-, ArbitraryTxHash(..)
-, ArbitraryTxIn(..)
-, ArbitraryTxOut(..)
-, ArbitraryOutPoint(..)
-, ArbitraryAddrOnlyTx(..)
-, ArbitraryAddrOnlyTxIn(..)
-, ArbitraryAddrOnlyTxOut(..)
-, ArbitrarySigInput(..)
-, ArbitraryPKSigInput(..)
-, ArbitraryPKHashSigInput(..)
-, ArbitraryMSSigInput(..)
-, ArbitrarySHSigInput(..)
-, ArbitrarySigningData(..)
-, ArbitraryPartialTxs(..)
-
-  -- * Block Arbitrary instances
-, ArbitraryBlock(..)
-, ArbitraryBlockHeader(..)
-, ArbitraryBlockHash(..)
-, ArbitraryGetBlocks(..)
-, ArbitraryGetHeaders(..)
-, ArbitraryHeaders(..)
-, ArbitraryMerkleBlock(..)
-) where
-
-import Network.Haskoin.Test.Util
-import Network.Haskoin.Test.Crypto
-import Network.Haskoin.Test.Node
-import Network.Haskoin.Test.Message
-import Network.Haskoin.Test.Script
-import Network.Haskoin.Test.Transaction
-import Network.Haskoin.Test.Block
diff --git a/Network/Haskoin/Test/Block.hs b/Network/Haskoin/Test/Block.hs
deleted file mode 100644
--- a/Network/Haskoin/Test/Block.hs
+++ /dev/null
@@ -1,110 +0,0 @@
-{-|
-  Arbitrary types for Network.Haskoin.Block
--}
-module Network.Haskoin.Test.Block
-( ArbitraryBlock(..)
-, ArbitraryBlockHeader(..)
-, ArbitraryBlockHash(..)
-, ArbitraryGetBlocks(..)
-, ArbitraryGetHeaders(..)
-, ArbitraryHeaders(..)
-, ArbitraryMerkleBlock(..)
-) where
-
-import Test.QuickCheck
-    ( Arbitrary
-    , arbitrary
-    , choose
-    , vectorOf
-    , listOf1
-    )
-
-import Network.Haskoin.Test.Crypto
-import Network.Haskoin.Test.Transaction
-import Network.Haskoin.Test.Node
-
-import Network.Haskoin.Block.Types
-import Network.Haskoin.Block.Merkle
-
--- | Arbitrary Block
-newtype ArbitraryBlock = ArbitraryBlock Block
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryBlock where
-    arbitrary = do
-        ArbitraryBlockHeader h <- arbitrary
-        c <- choose (0,10)
-        txs <- map (\(ArbitraryTx x) -> x) <$> vectorOf c arbitrary
-        return $ ArbitraryBlock $ Block h txs
-
--- | Arbitrary BlockHeader
-newtype ArbitraryBlockHeader = ArbitraryBlockHeader BlockHeader
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryBlockHeader where
-    arbitrary = do
-        ArbitraryBlockHash h1 <- arbitrary
-        ArbitraryHash256 h2 <- arbitrary
-        h <- createBlockHeader <$> arbitrary <*> return h1 <*> return h2
-                               <*> arbitrary <*> arbitrary <*> arbitrary
-        return $ ArbitraryBlockHeader h
-
-newtype ArbitraryBlockHash = ArbitraryBlockHash BlockHash
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryBlockHash where
-    arbitrary = do
-        ArbitraryHash256 h <- arbitrary
-        return $ ArbitraryBlockHash $ BlockHash h
-
--- | Arbitrary GetBlocks
-newtype ArbitraryGetBlocks = ArbitraryGetBlocks GetBlocks
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryGetBlocks where
-    arbitrary = do
-        hs <- listOf1 arbitrary
-        let hs' = map (\(ArbitraryBlockHash h) -> h) hs
-        ArbitraryBlockHash h <- arbitrary
-        b <- GetBlocks <$> arbitrary <*> return hs' <*> return h
-        return $ ArbitraryGetBlocks b
-
--- | Arbitrary GetHeaders
-newtype ArbitraryGetHeaders = ArbitraryGetHeaders GetHeaders
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryGetHeaders where
-    arbitrary = do
-        hs <- listOf1 arbitrary
-        let hs' = map (\(ArbitraryBlockHash h) -> h) hs
-        ArbitraryBlockHash h' <- arbitrary
-        h <- GetHeaders <$> arbitrary <*> return hs' <*> return h'
-        return $ ArbitraryGetHeaders h
-
--- | Arbitrary Headers
-newtype ArbitraryHeaders = ArbitraryHeaders Headers
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryHeaders where
-    arbitrary = ArbitraryHeaders <$> do
-        xs <- listOf1 $ do
-            ArbitraryBlockHeader h <- arbitrary
-            ArbitraryVarInt v <- arbitrary
-            return (h,v)
-        return $ Headers xs
-
--- | Arbitrary MerkleBlock
-newtype ArbitraryMerkleBlock = ArbitraryMerkleBlock MerkleBlock
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryMerkleBlock where
-    arbitrary = ArbitraryMerkleBlock <$> do
-        ArbitraryBlockHeader bh <- arbitrary
-        ntx <- arbitrary
-        hashes <- listOf1 arbitrary
-        let hashes' = map (\(ArbitraryHash256 h) -> h) hashes
-        c <- choose (1,10)
-        flags <- vectorOf (c*8) arbitrary
-        return $ MerkleBlock bh ntx hashes' flags
-
-
diff --git a/Network/Haskoin/Test/Crypto.hs b/Network/Haskoin/Test/Crypto.hs
deleted file mode 100644
--- a/Network/Haskoin/Test/Crypto.hs
+++ /dev/null
@@ -1,258 +0,0 @@
-{-|
-  Arbitrary types for Network.Haskoin.Crypto
--}
-module Network.Haskoin.Test.Crypto
-( ArbitraryHash512(..)
-, ArbitraryHash256(..)
-, ArbitraryHash160(..)
-, ArbitraryCheckSum32(..)
-, ArbitraryByteString(..)
-, ArbitraryNotNullByteString(..)
-, ArbitraryPrvKey(..)
-, ArbitraryPrvKeyC(..)
-, ArbitraryPrvKeyU(..)
-, ArbitraryPubKey(..)
-, ArbitraryPubKeyC(..)
-, ArbitraryPubKeyU(..)
-, ArbitraryAddress(..)
-, ArbitraryPubKeyAddress(..)
-, ArbitraryScriptAddress(..)
-, ArbitrarySignature(..)
-, ArbitraryXPrvKey(..)
-, ArbitraryXPubKey(..)
-, ArbitraryHardPath(..)
-, ArbitrarySoftPath(..)
-, ArbitraryDerivPath(..)
-, ArbitraryParsedPath(..)
-
-) where
-
-import Test.QuickCheck
-    ( Arbitrary
-    , Gen
-    , arbitrary
-    , oneof
-    , vectorOf
-    , listOf
-    )
-
-import Crypto.Secp256k1 ()
-
-import Data.Bits (clearBit)
-import qualified Data.ByteString as BS (pack)
-import Data.Maybe (fromMaybe)
-import Data.Word (Word32)
-
-import Network.Haskoin.Test.Util
-import Network.Haskoin.Crypto.ECDSA
-import Network.Haskoin.Crypto.Hash
-import Network.Haskoin.Crypto.Keys
-import Network.Haskoin.Crypto.Base58
-import Network.Haskoin.Crypto.ExtendedKeys
-import Data.List (foldl')
-
-newtype ArbitraryHash160 = ArbitraryHash160 Hash160
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryHash160 where
-    arbitrary = (ArbitraryHash160 . fromMaybe e . bsToHash160 . BS.pack) <$>
-        vectorOf 20 arbitrary
-      where
-        e = error "Could not read arbitrary 20-byte hash"
-
-newtype ArbitraryHash256 = ArbitraryHash256 Hash256
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryHash256 where
-    arbitrary = (ArbitraryHash256 . fromMaybe e . bsToHash256 . BS.pack) <$>
-        vectorOf 32 arbitrary
-      where
-        e = error "Could not read arbitrary 32-byte hash"
-
-newtype ArbitraryHash512 = ArbitraryHash512 Hash512
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryHash512 where
-    arbitrary = (ArbitraryHash512 . fromMaybe e . bsToHash512 . BS.pack) <$>
-        vectorOf 64 arbitrary
-      where
-        e = error "Could not read arbitrary 64-byte hash"
-
-newtype ArbitraryCheckSum32 = ArbitraryCheckSum32 CheckSum32
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryCheckSum32 where
-    arbitrary = (ArbitraryCheckSum32 . fromMaybe e . bsToCheckSum32 . BS.pack) <$>
-        vectorOf 4 arbitrary
-      where
-        e = error "Could not read arbitrary checksum"
-
--- | Arbitrary private key (can be both compressed or uncompressed)
-newtype ArbitraryPrvKey = ArbitraryPrvKey PrvKey
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPrvKey where
-    arbitrary = ArbitraryPrvKey <$> oneof
-        [ arbitrary >>= \(ArbitraryPrvKeyC k) -> return (toPrvKeyG k)
-        , arbitrary >>= \(ArbitraryPrvKeyU k) -> return (toPrvKeyG k)
-        ]
-
--- | Arbitrary compressed private key
-newtype ArbitraryPrvKeyC = ArbitraryPrvKeyC PrvKeyC
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPrvKeyC where
-    arbitrary = do
-        i <- arbitrary
-        return $ ArbitraryPrvKeyC $ makePrvKeyC i
-
--- | Arbitrary uncompressed private key
-newtype ArbitraryPrvKeyU = ArbitraryPrvKeyU PrvKeyU
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPrvKeyU where
-    arbitrary = do
-        i <- arbitrary
-        return $ ArbitraryPrvKeyU $ makePrvKeyU i
-
--- | Arbitrary public key (can be both compressed or uncompressed) with its
--- corresponding private key.
-data ArbitraryPubKey = ArbitraryPubKey PrvKey PubKey
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPubKey where
-    arbitrary = oneof
-        [ arbitrary >>= \(ArbitraryPubKeyC k p) ->
-            return $ ArbitraryPubKey (toPrvKeyG k) (toPubKeyG p)
-        , arbitrary >>= \(ArbitraryPubKeyU k p) ->
-            return $ ArbitraryPubKey (toPrvKeyG k) (toPubKeyG p)
-        ]
-
--- | Arbitrary compressed public key with its corresponding private key.
-data ArbitraryPubKeyC = ArbitraryPubKeyC PrvKeyC PubKeyC
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPubKeyC where
-    arbitrary = do
-        ArbitraryPrvKeyC k <- arbitrary
-        return $ ArbitraryPubKeyC k $ derivePubKey k
-
--- | Arbitrary uncompressed public key with its corresponding private key.
-data ArbitraryPubKeyU = ArbitraryPubKeyU PrvKeyU PubKeyU
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPubKeyU where
-    arbitrary = do
-        ArbitraryPrvKeyU k <- arbitrary
-        return $ ArbitraryPubKeyU k $ derivePubKey k
-
--- | Arbitrary address (can be a pubkey or script hash address)
-newtype ArbitraryAddress = ArbitraryAddress Address
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryAddress where
-    arbitrary = ArbitraryAddress <$> oneof
-        [ arbitrary >>= \(ArbitraryPubKeyAddress a) -> return a
-        , arbitrary >>= \(ArbitraryScriptAddress a) -> return a
-        ]
-
--- | Arbitrary public key hash address
-newtype ArbitraryPubKeyAddress = ArbitraryPubKeyAddress Address
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPubKeyAddress where
-    arbitrary = do
-        ArbitraryHash160 i <- arbitrary
-        return $ ArbitraryPubKeyAddress $ PubKeyAddress i
-
--- | Arbitrary script hash address
-newtype ArbitraryScriptAddress = ArbitraryScriptAddress Address
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryScriptAddress where
-    arbitrary = do
-        ArbitraryHash160 i <- arbitrary
-        return $ ArbitraryScriptAddress $ ScriptAddress i
-
--- | Arbitrary message hash, private key, nonce and corresponding signature.
--- The signature is generated with a random message, random private key and a
--- random nonce.
-data ArbitrarySignature = ArbitrarySignature Hash256 PrvKey Signature
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitrarySignature where
-    arbitrary = do
-        ArbitraryHash256 msg <- arbitrary
-        ArbitraryPrvKey key <- arbitrary
-        let sig = signMsg msg key
-        return $ ArbitrarySignature msg key sig
-
--- | Arbitrary extended private key.
-data ArbitraryXPrvKey = ArbitraryXPrvKey XPrvKey
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryXPrvKey where
-    arbitrary = do
-        d <- arbitrary
-        p <- arbitrary
-        i <- arbitrary
-        ArbitraryHash256 c <- arbitrary
-        ArbitraryPrvKeyC k <- arbitrary
-        return $ ArbitraryXPrvKey $ XPrvKey d p i c k
-
--- | Arbitrary extended public key with its corresponding private key.
-data ArbitraryXPubKey = ArbitraryXPubKey XPrvKey XPubKey
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryXPubKey where
-    arbitrary = do
-        ArbitraryXPrvKey k <- arbitrary
-        return $ ArbitraryXPubKey k $ deriveXPubKey k
-
-{- Custom derivations -}
-
-genIndex :: Gen Word32
-genIndex = (`clearBit` 31) <$> arbitrary
-
-data ArbitraryBip32PathIndex = ArbitraryBip32PathIndex Bip32PathIndex
-    deriving (Show,Eq)
-
-instance Arbitrary ArbitraryBip32PathIndex where
-    arbitrary = 
-        ArbitraryBip32PathIndex <$> oneof [soft, hard]
-        where soft = Bip32SoftIndex <$> genIndex
-              hard = Bip32HardIndex <$> genIndex
-
-data ArbitraryHardPath = ArbitraryHardPath HardPath
-    deriving (Show, Eq)
-
-instance Arbitrary ArbitraryHardPath where
-    arbitrary =
-        ArbitraryHardPath . foldl' (:|) Deriv <$> listOf genIndex
-
-
-data ArbitrarySoftPath = ArbitrarySoftPath SoftPath
-    deriving (Show, Eq)
-
-instance Arbitrary ArbitrarySoftPath where
-    arbitrary =
-        ArbitrarySoftPath . foldl' (:/) Deriv <$> listOf genIndex
-
-data ArbitraryDerivPath = ArbitraryDerivPath DerivPath
-    deriving (Show, Eq)
-
-instance Arbitrary ArbitraryDerivPath where    
-    arbitrary = ArbitraryDerivPath . concatBip32Segments . map (\(ArbitraryBip32PathIndex i) -> i ) <$> arbitrary  
-        
-
-data ArbitraryParsedPath = ArbitraryParsedPath ParsedPath 
-  deriving (Show, Eq)
-
-instance Arbitrary ArbitraryParsedPath where
-    arbitrary = do
-        ArbitraryDerivPath d <- arbitrary 
-        ArbitraryParsedPath <$> oneof [ pure $ ParsedPrv d
-                                      , pure $ ParsedPub d
-                                      , pure $ ParsedEmpty d ]
-
-
diff --git a/Network/Haskoin/Test/Message.hs b/Network/Haskoin/Test/Message.hs
deleted file mode 100644
--- a/Network/Haskoin/Test/Message.hs
+++ /dev/null
@@ -1,61 +0,0 @@
-{-|
-  Arbitrary types for Network.Haskoin.Node.Message
--}
-module Network.Haskoin.Test.Message
-( ArbitraryMessageHeader(..)
-, ArbitraryMessage(..)
-) where
-
-import Test.QuickCheck
-    ( Arbitrary
-    , arbitrary
-    , oneof
-    )
-
-import Network.Haskoin.Test.Crypto
-import Network.Haskoin.Test.Node
-import Network.Haskoin.Test.Transaction
-import Network.Haskoin.Test.Block
-
-import Network.Haskoin.Node.Message
-
--- | Arbitrary MessageHeader
-newtype ArbitraryMessageHeader = ArbitraryMessageHeader MessageHeader
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryMessageHeader where
-    arbitrary = ArbitraryMessageHeader <$> do
-        m <- arbitrary
-        ArbitraryMessageCommand mc <- arbitrary
-        p <- arbitrary
-        ArbitraryCheckSum32 c <- arbitrary
-        return $ MessageHeader m mc p c
-
--- | Arbitrary Message
-newtype ArbitraryMessage = ArbitraryMessage Message
-    deriving (Eq, Show)
-
-instance Arbitrary ArbitraryMessage where
-    arbitrary = ArbitraryMessage <$> oneof
-        [ arbitrary >>= \(ArbitraryVersion x) -> return $ MVersion x
-        , return MVerAck
-        , arbitrary >>= \(ArbitraryAddr x) -> return $ MAddr x
-        , arbitrary >>= \(ArbitraryInv x) -> return $ MInv x
-        , arbitrary >>= \(ArbitraryGetData x) -> return $ MGetData x
-        , arbitrary >>= \(ArbitraryNotFound x) -> return $ MNotFound x
-        , arbitrary >>= \(ArbitraryGetBlocks x) -> return $ MGetBlocks x
-        , arbitrary >>= \(ArbitraryGetHeaders x) -> return $ MGetHeaders x
-        , arbitrary >>= \(ArbitraryTx x) -> return $ MTx x
-        , arbitrary >>= \(ArbitraryBlock x) -> return $ MBlock x
-        , arbitrary >>= \(ArbitraryMerkleBlock x) -> return $ MMerkleBlock x
-        , arbitrary >>= \(ArbitraryHeaders x) -> return $ MHeaders x
-        , return MGetAddr
-        , arbitrary >>= \(ArbitraryFilterLoad x) -> return $ MFilterLoad x
-        , arbitrary >>= \(ArbitraryFilterAdd x) -> return $ MFilterAdd x
-        , return MFilterClear
-        , arbitrary >>= \(ArbitraryPing x) -> return $ MPing x
-        , arbitrary >>= \(ArbitraryPong x) -> return $ MPong x
-        , arbitrary >>= \(ArbitraryAlert x) -> return $ MAlert x
-        , arbitrary >>= \(ArbitraryReject x) -> return $ MReject x
-        ]
-
diff --git a/Network/Haskoin/Test/Node.hs b/Network/Haskoin/Test/Node.hs
deleted file mode 100644
--- a/Network/Haskoin/Test/Node.hs
+++ /dev/null
@@ -1,288 +0,0 @@
-{-|
-  Arbitrary types for Network.Haskoin.Node
--}
-module Network.Haskoin.Test.Node
-( ArbitraryVarInt(..)
-, ArbitraryVarString(..)
-, ArbitraryNetworkAddress(..)
-, ArbitraryNetworkAddressTime(..)
-, ArbitraryInvType(..)
-, ArbitraryInvVector(..)
-, ArbitraryInv(..)
-, ArbitraryVersion(..)
-, ArbitraryAddr(..)
-, ArbitraryAlert(..)
-, ArbitraryReject(..)
-, ArbitraryRejectCode(..)
-, ArbitraryGetData(..)
-, ArbitraryNotFound(..)
-, ArbitraryPing(..)
-, ArbitraryPong(..)
-, ArbitraryBloomFlags(..)
-, ArbitraryBloomFilter(..)
-, ArbitraryFilterLoad(..)
-, ArbitraryFilterAdd(..)
-, ArbitraryMessageCommand(..)
-) where
-
-import Test.QuickCheck
-    ( Arbitrary
-    , arbitrary
-    , elements
-    , listOf1
-    , oneof
-    , choose
-    , vectorOf
-    )
-
-import Data.Word (Word16, Word32)
-import qualified Data.ByteString as BS (pack, empty)
-
-import Network.Socket (SockAddr(..))
-
-import Network.Haskoin.Test.Crypto
-import Network.Haskoin.Node
-
--- | Arbitrary VarInt
-newtype ArbitraryVarInt = ArbitraryVarInt VarInt
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryVarInt where
-    arbitrary = ArbitraryVarInt . VarInt <$> arbitrary
-
--- | Arbitrary VarString
-newtype ArbitraryVarString = ArbitraryVarString VarString
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryVarString where
-    arbitrary = do
-        ArbitraryByteString bs <- arbitrary
-        return $ ArbitraryVarString $ VarString bs
-
--- | Arbitrary NetworkAddress
-newtype ArbitraryNetworkAddress = ArbitraryNetworkAddress NetworkAddress
-    deriving (Eq, Show)
-
-instance Arbitrary ArbitraryNetworkAddress where
-    arbitrary = do
-        s <- arbitrary
-        a <- arbitrary
-        p <- arbitrary
-        ArbitraryNetworkAddress . (NetworkAddress s) <$> oneof
-            [ do
-                b <- arbitrary
-                c <- arbitrary
-                d <- arbitrary
-                return $ SockAddrInet6 (fromIntegral p) 0 (a,b,c,d) 0
-            , return $ SockAddrInet (fromIntegral (p :: Word16)) a
-            ]
-
--- | Arbitrary NetworkAddressTime
-newtype ArbitraryNetworkAddressTime
-    = ArbitraryNetworkAddressTime (Word32, NetworkAddress)
-
-instance Arbitrary ArbitraryNetworkAddressTime where
-    arbitrary = do
-        w <- arbitrary
-        ArbitraryNetworkAddress a <- arbitrary
-        return $ ArbitraryNetworkAddressTime (w,a)
-
--- | Arbitrary InvType
-newtype ArbitraryInvType = ArbitraryInvType InvType
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryInvType where
-    arbitrary = ArbitraryInvType <$> elements
-        [InvError, InvTx, InvBlock, InvMerkleBlock]
-
--- | Arbitrary InvVector
-newtype ArbitraryInvVector = ArbitraryInvVector InvVector
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryInvVector where
-    arbitrary = do
-        ArbitraryInvType t <- arbitrary
-        ArbitraryHash256 h <- arbitrary
-        return $ ArbitraryInvVector $ InvVector t h
-
--- | Arbitrary non-empty Inv
-newtype ArbitraryInv = ArbitraryInv Inv
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryInv where
-    arbitrary = do
-        vs <- listOf1 arbitrary
-        return $ ArbitraryInv $ Inv $ map (\(ArbitraryInvVector v) -> v) vs
-
--- | Arbitrary Version
-newtype ArbitraryVersion = ArbitraryVersion Version
-    deriving (Eq, Show)
-
-instance Arbitrary ArbitraryVersion where
-    arbitrary = do
-        v <- arbitrary
-        s <- arbitrary
-        t <- arbitrary
-        ArbitraryNetworkAddress nr <- arbitrary
-        ArbitraryNetworkAddress ns <- arbitrary
-        n <- arbitrary
-        ArbitraryVarString a <- arbitrary
-        h <- arbitrary
-        r <- arbitrary
-        return $ ArbitraryVersion $ Version v s t nr ns n a h r
-
--- | Arbitrary non-empty Addr
-newtype ArbitraryAddr = ArbitraryAddr Addr
-    deriving (Eq, Show)
-
-instance Arbitrary ArbitraryAddr where
-    arbitrary = do
-       vs <- listOf1 arbitrary
-       return $ ArbitraryAddr $ Addr $
-           map (\(ArbitraryNetworkAddressTime x) -> x) vs
-
--- | Arbitrary alert with random payload and signature. Signature is not
--- valid.
-newtype ArbitraryAlert = ArbitraryAlert Alert
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryAlert where
-    arbitrary = do
-        ArbitraryVarString p <- arbitrary
-        ArbitraryVarString s <- arbitrary
-        return $ ArbitraryAlert $ Alert p s
-
--- | Arbitrary Reject
-newtype ArbitraryReject = ArbitraryReject Reject
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryReject where
-    arbitrary = do
-        ArbitraryMessageCommand m <- arbitrary
-        ArbitraryRejectCode c <- arbitrary
-        ArbitraryVarString s <- arbitrary
-        d <- oneof [ return BS.empty
-                   , BS.pack <$> vectorOf 32 arbitrary
-                   ]
-        return $ ArbitraryReject $ Reject m c s d
-
--- | Arbitrary RejectCode
-newtype ArbitraryRejectCode = ArbitraryRejectCode RejectCode
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryRejectCode where
-    arbitrary = ArbitraryRejectCode <$> elements
-        [ RejectMalformed
-        , RejectInvalid
-        , RejectInvalid
-        , RejectDuplicate
-        , RejectNonStandard
-        , RejectDust
-        , RejectInsufficientFee
-        , RejectCheckpoint
-        ]
-
--- | Arbitrary non-empty GetData
-newtype ArbitraryGetData = ArbitraryGetData GetData
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryGetData where
-    arbitrary = do
-        vs <- listOf1 arbitrary
-        return $ ArbitraryGetData $ GetData $
-            map (\(ArbitraryInvVector x) -> x) vs
-
--- | Arbitrary NotFound
-newtype ArbitraryNotFound = ArbitraryNotFound NotFound
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryNotFound where
-    arbitrary = do
-        vs <- listOf1 arbitrary
-        return $ ArbitraryNotFound $ NotFound $
-            map (\(ArbitraryInvVector x) -> x) vs
-
--- | Arbitrary Ping
-newtype ArbitraryPing = ArbitraryPing Ping
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPing where
-    arbitrary = ArbitraryPing . Ping <$> arbitrary
-
--- | Arbitrary Pong
-newtype ArbitraryPong = ArbitraryPong Pong
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPong where
-    arbitrary = ArbitraryPong . Pong <$> arbitrary
-
--- | Arbitrary bloom filter flags
-data ArbitraryBloomFlags = ArbitraryBloomFlags BloomFlags
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryBloomFlags where
-    arbitrary = ArbitraryBloomFlags <$> elements
-        [ BloomUpdateNone
-        , BloomUpdateAll
-        , BloomUpdateP2PubKeyOnly
-        ]
-
--- | Arbitrary bloom filter with its corresponding number of elements
--- and false positive rate.
-data ArbitraryBloomFilter = ArbitraryBloomFilter Int Double BloomFilter
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryBloomFilter where
-    arbitrary = do
-        n     <- choose (0,100000)
-        fp    <- choose (1e-8,1)
-        tweak <- arbitrary
-        ArbitraryBloomFlags fl <- arbitrary
-        return $ ArbitraryBloomFilter n fp $ bloomCreate n fp tweak fl
-
--- | Arbitrary FilterLoad
-data ArbitraryFilterLoad = ArbitraryFilterLoad FilterLoad
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryFilterLoad where
-    arbitrary = do
-        ArbitraryBloomFilter _ _ bf <- arbitrary
-        return $ ArbitraryFilterLoad $ FilterLoad bf
-
--- | Arbitrary FilterAdd
-data ArbitraryFilterAdd = ArbitraryFilterAdd FilterAdd
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryFilterAdd where
-    arbitrary = do
-        ArbitraryByteString bs <- arbitrary
-        return $ ArbitraryFilterAdd $ FilterAdd bs
-
-
--- | Arbitrary MessageCommand
-newtype ArbitraryMessageCommand = ArbitraryMessageCommand MessageCommand
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryMessageCommand where
-    arbitrary = ArbitraryMessageCommand <$> elements
-        [ MCVersion
-        , MCVerAck
-        , MCAddr
-        , MCInv
-        , MCGetData
-        , MCNotFound
-        , MCGetBlocks
-        , MCGetHeaders
-        , MCTx
-        , MCBlock
-        , MCMerkleBlock
-        , MCHeaders
-        , MCGetAddr
-        , MCFilterLoad
-        , MCFilterAdd
-        , MCFilterClear
-        , MCPing
-        , MCPong
-        , MCAlert
-        ]
-
diff --git a/Network/Haskoin/Test/Script.hs b/Network/Haskoin/Test/Script.hs
deleted file mode 100644
--- a/Network/Haskoin/Test/Script.hs
+++ /dev/null
@@ -1,423 +0,0 @@
-{-|
-  Arbitrary types for Network.Haskoin.Script
--}
-module Network.Haskoin.Test.Script
-( ArbitraryScriptOp(..)
-, ArbitraryScript(..)
-, ArbitraryIntScriptOp(..)
-, ArbitraryPushDataType(..)
-, ArbitraryTxSignature(..)
-, ArbitrarySigHash(..)
-, ArbitraryValidSigHash(..)
-, ArbitraryMSParam(..)
-, ArbitraryScriptOutput(..)
-, ArbitrarySimpleOutput(..)
-, ArbitraryPKOutput(..)
-, ArbitraryPKHashOutput(..)
-, ArbitraryMSOutput(..)
-, ArbitraryMSCOutput(..)
-, ArbitrarySHOutput(..)
-, ArbitraryScriptInput(..)
-, ArbitrarySimpleInput(..)
-, ArbitraryPKInput(..)
-, ArbitraryPKHashInput(..)
-, ArbitraryPKHashCInput(..)
-, ArbitraryMSInput(..)
-, ArbitrarySHInput(..)
-, ArbitraryMulSigSHCInput(..)
-) where
-
-import Test.QuickCheck
-    ( Arbitrary
-    , arbitrary
-    , oneof
-    , choose
-    , vectorOf
-    , elements
-    )
-
-import Data.Bits (testBit)
-
-import Network.Haskoin.Transaction.Types
-import Network.Haskoin.Test.Crypto
-import Network.Haskoin.Script
-import Network.Haskoin.Crypto
-
--- | Arbitrary Script with random script ops
-newtype ArbitraryScript = ArbitraryScript Script
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryScript where
-    arbitrary = do
-        vs <- arbitrary
-        return $ ArbitraryScript $ Script $ map f vs
-      where
-        f (ArbitraryScriptOp op) = op
-
--- | Arbitrary ScriptOp (push operations have random data)
-newtype ArbitraryScriptOp = ArbitraryScriptOp ScriptOp
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryScriptOp where
-    arbitrary = ArbitraryScriptOp <$> oneof
-        [ -- Pushing Data
-         arbitrary >>= \(ArbitraryNotNullByteString bs) ->
-            return $ opPushData bs
-        ,return OP_0
-        ,return OP_1NEGATE
-        ,return OP_RESERVED
-        ,return OP_1 , return OP_2 , return OP_3 , return OP_4
-        ,return OP_5 , return OP_6 , return OP_7 , return OP_8
-        ,return OP_9 , return OP_10, return OP_11, return OP_12
-        ,return OP_13, return OP_14, return OP_15, return OP_16
-
-        -- Flow control
-        ,return OP_NOP
-        ,return OP_VER
-        ,return OP_IF
-        ,return OP_NOTIF
-        ,return OP_VERIF
-        ,return OP_VERNOTIF
-        ,return OP_ELSE
-        ,return OP_ENDIF
-        ,return OP_VERIFY
-        ,return OP_RETURN
-
-        -- Stack operations
-        ,return OP_TOALTSTACK
-        ,return OP_FROMALTSTACK
-        ,return OP_IFDUP
-        ,return OP_DEPTH
-        ,return OP_DROP
-        ,return OP_DUP
-        ,return OP_NIP
-        ,return OP_OVER
-        ,return OP_PICK
-        ,return OP_ROLL
-        ,return OP_ROT
-        ,return OP_SWAP
-        ,return OP_TUCK
-        ,return OP_2DROP
-        ,return OP_2DUP
-        ,return OP_3DUP
-        ,return OP_2OVER
-        ,return OP_2ROT
-        ,return OP_2SWAP
-
-        -- Splice
-        ,return OP_CAT
-        ,return OP_SUBSTR
-        ,return OP_LEFT
-        ,return OP_RIGHT
-        ,return OP_SIZE
-
-        -- Bitwise logic
-        ,return OP_INVERT
-        ,return OP_AND
-        ,return OP_OR
-        ,return OP_XOR
-        ,return OP_EQUAL
-        ,return OP_EQUALVERIFY
-        ,return OP_RESERVED1
-        ,return OP_RESERVED2
-
-        -- Arithmetic
-        ,return OP_1ADD
-        ,return OP_1SUB
-        ,return OP_2MUL
-        ,return OP_2DIV
-        ,return OP_NEGATE
-        ,return OP_ABS
-        ,return OP_NOT
-        ,return OP_0NOTEQUAL
-        ,return OP_ADD
-        ,return OP_SUB
-        ,return OP_MUL
-        ,return OP_DIV
-        ,return OP_MOD
-        ,return OP_LSHIFT
-        ,return OP_RSHIFT
-        ,return OP_BOOLAND
-        ,return OP_BOOLOR
-        ,return OP_NUMEQUAL
-        ,return OP_NUMEQUALVERIFY
-        ,return OP_NUMNOTEQUAL
-        ,return OP_LESSTHAN
-        ,return OP_GREATERTHAN
-        ,return OP_LESSTHANOREQUAL
-        ,return OP_GREATERTHANOREQUAL
-        ,return OP_MIN
-        ,return OP_MAX
-        ,return OP_WITHIN
-
-        -- Crypto
-        ,return OP_RIPEMD160
-        ,return OP_SHA1
-        ,return OP_SHA256
-        ,return OP_HASH160
-        ,return OP_HASH256
-        ,return OP_CODESEPARATOR
-        ,return OP_CHECKSIG
-        ,return OP_CHECKSIGVERIFY
-        ,return OP_CHECKMULTISIG
-        ,return OP_CHECKMULTISIGVERIFY
-
-        -- Expansion
-        ,return OP_NOP1, return OP_NOP2
-        ,return OP_NOP3, return OP_NOP4
-        ,return OP_NOP5, return OP_NOP6
-        ,return OP_NOP7, return OP_NOP8
-        ,return OP_NOP9, return OP_NOP10
-
-        -- Other
-        ,return OP_PUBKEYHASH
-        ,return OP_PUBKEY
-        ,return $ OP_INVALIDOPCODE 0xff
-        ]
-
--- | Arbtirary ScriptOp with a value in [OP_1 .. OP_16]
-newtype ArbitraryIntScriptOp = ArbitraryIntScriptOp ScriptOp
-    deriving (Eq, Show)
-
-instance Arbitrary ArbitraryIntScriptOp where
-    arbitrary = ArbitraryIntScriptOp <$> elements
-        [ OP_1,  OP_2,  OP_3,  OP_4
-        , OP_5,  OP_6,  OP_7,  OP_8
-        , OP_9,  OP_10, OP_11, OP_12
-        , OP_13, OP_14, OP_15, OP_16
-        ]
-
--- | Arbitrary PushDataType
-newtype ArbitraryPushDataType = ArbitraryPushDataType PushDataType
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPushDataType where
-    arbitrary = ArbitraryPushDataType <$> elements
-        [ OPCODE, OPDATA1, OPDATA2, OPDATA4 ]
-
--- | Arbitrary SigHash (including invalid/unknown sighash codes)
-newtype ArbitrarySigHash = ArbitrarySigHash SigHash
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitrarySigHash where
-    arbitrary = ArbitrarySigHash <$> oneof
-        [ SigAll    <$> arbitrary
-        , SigNone   <$> arbitrary
-        , SigSingle <$> arbitrary
-        , f
-        ]
-      where
-        f = do
-            -- avoid valid SigHash bytes
-            w <- elements $ 0x00 : 0x80 : [0x04..0x7f] ++ [0x84..0xff]
-            return $ SigUnknown (testBit w 7) w
-
--- | Arbitrary valid SigHash
-newtype ArbitraryValidSigHash = ArbitraryValidSigHash SigHash
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryValidSigHash where
-    arbitrary = ArbitraryValidSigHash <$> oneof
-        [ SigAll    <$> arbitrary
-        , SigNone   <$> arbitrary
-        , SigSingle <$> arbitrary
-        ]
-
--- | Arbitrary message hash, private key and corresponding TxSignature. The
--- signature is generated deterministically using a random message and a
--- random private key.
-data ArbitraryTxSignature =
-    ArbitraryTxSignature TxHash PrvKey TxSignature
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryTxSignature where
-    arbitrary = do
-        ArbitrarySignature msg key sig <- arbitrary
-        ArbitrarySigHash sh <- arbitrary
-        let txsig = TxSignature sig sh
-        return $ ArbitraryTxSignature (TxHash msg) key txsig
-
--- | Arbitrary m of n parameters
-data ArbitraryMSParam = ArbitraryMSParam Int Int
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryMSParam where
-    arbitrary = do
-        m <- choose (1,16)
-        n <- choose (m,16)
-        return $ ArbitraryMSParam m n
-
--- | Arbitrary ScriptOutput (Can by any valid type)
-newtype ArbitraryScriptOutput = ArbitraryScriptOutput ScriptOutput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryScriptOutput where
-    arbitrary = ArbitraryScriptOutput <$> oneof
-        [ arbitrary >>= \(ArbitraryPKOutput o) -> return o
-        , arbitrary >>= \(ArbitraryPKHashOutput o) -> return o
-        , arbitrary >>= \(ArbitraryMSOutput o) -> return o
-        , arbitrary >>= \(ArbitrarySHOutput o) -> return o
-        , arbitrary >>= \(ArbitraryDCOutput o) -> return o
-        ]
-
--- | Arbitrary ScriptOutput of type PayPK, PayPKHash or PayMS
--- (Not PayScriptHash or DataCarrier)
-newtype ArbitrarySimpleOutput = ArbitrarySimpleOutput ScriptOutput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitrarySimpleOutput where
-    arbitrary = ArbitrarySimpleOutput <$> oneof
-        [ arbitrary >>= \(ArbitraryPKOutput o) -> return o
-        , arbitrary >>= \(ArbitraryPKHashOutput o) -> return o
-        , arbitrary >>= \(ArbitraryMSOutput o) -> return o
-        ]
-
--- | Arbitrary ScriptOutput of type PayPK
-newtype ArbitraryPKOutput = ArbitraryPKOutput ScriptOutput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPKOutput where
-    arbitrary = do
-        ArbitraryPubKey _ key <- arbitrary
-        return $ ArbitraryPKOutput $ PayPK key
-
--- | Arbitrary ScriptOutput of type PayPKHash
-newtype ArbitraryPKHashOutput = ArbitraryPKHashOutput ScriptOutput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPKHashOutput where
-    arbitrary = do
-        ArbitraryPubKeyAddress a <- arbitrary
-        return $ ArbitraryPKHashOutput $ PayPKHash a
-
--- | Arbitrary ScriptOutput of type PayMS
-newtype ArbitraryMSOutput = ArbitraryMSOutput ScriptOutput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryMSOutput where
-    arbitrary = do
-        ArbitraryMSParam m n <- arbitrary
-        keys <- map f <$> vectorOf n arbitrary
-        return $ ArbitraryMSOutput $ PayMulSig keys m
-      where
-        f (ArbitraryPubKey _ key) = key
-
--- | Arbitrary ScriptOutput of type PayMS containing only compressed keys
-newtype ArbitraryMSCOutput = ArbitraryMSCOutput ScriptOutput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryMSCOutput where
-    arbitrary = do
-        ArbitraryMSParam m n <- arbitrary
-        keys <- map f <$> vectorOf n arbitrary
-        return $ ArbitraryMSCOutput $ PayMulSig keys m
-      where
-        f (ArbitraryPubKeyC _ key) = toPubKeyG key
-
--- | Arbitrary ScriptOutput of type PayScriptHash
-newtype ArbitrarySHOutput = ArbitrarySHOutput ScriptOutput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitrarySHOutput where
-    arbitrary = do
-        ArbitraryScriptAddress a <- arbitrary
-        return $ ArbitrarySHOutput $ PayScriptHash a
-
--- | Arbitrary ScriptOutput of type DataCarrier
-newtype ArbitraryDCOutput = ArbitraryDCOutput ScriptOutput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryDCOutput where
-    arbitrary = do
-        ArbitraryNotNullByteString bs <- arbitrary
-        return $ ArbitraryDCOutput $ DataCarrier bs
-
--- | Arbitrary ScriptInput
-newtype ArbitraryScriptInput = ArbitraryScriptInput ScriptInput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryScriptInput where
-    arbitrary = ArbitraryScriptInput <$> oneof
-        [ arbitrary >>= \(ArbitraryPKInput i) -> return i
-        , arbitrary >>= \(ArbitraryPKHashInput i) -> return i
-        , arbitrary >>= \(ArbitraryMSInput i) -> return i
-        , arbitrary >>= \(ArbitrarySHInput i) -> return i
-        ]
-
--- | Arbitrary ScriptInput of type SpendPK, SpendPKHash or SpendMulSig
--- (not ScriptHashInput)
-newtype ArbitrarySimpleInput = ArbitrarySimpleInput ScriptInput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitrarySimpleInput where
-    arbitrary = ArbitrarySimpleInput <$> oneof
-        [ arbitrary >>= \(ArbitraryPKInput i) -> return i
-        , arbitrary >>= \(ArbitraryPKHashInput i) -> return i
-        , arbitrary >>= \(ArbitraryMSInput i) -> return i
-        ]
-
--- | Arbitrary ScriptInput of type SpendPK
-newtype ArbitraryPKInput = ArbitraryPKInput ScriptInput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPKInput where
-    arbitrary = ArbitraryPKInput . RegularInput . SpendPK <$>
-        (arbitrary >>= \(ArbitraryTxSignature _ _ sig) -> return sig)
-
--- | Arbitrary ScriptInput of type SpendPK
-newtype ArbitraryPKHashInput = ArbitraryPKHashInput ScriptInput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPKHashInput where
-    arbitrary = do
-        sig <- arbitrary >>= \(ArbitraryTxSignature _ _ sig) -> return sig
-        ArbitraryPubKey _ key <- arbitrary
-        return $ ArbitraryPKHashInput $ RegularInput $ SpendPKHash sig key
-
--- | Arbitrary ScriptInput of type SpendPK with a compressed public key
-newtype ArbitraryPKHashCInput = ArbitraryPKHashCInput ScriptInput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPKHashCInput where
-    arbitrary = do
-        sig <- arbitrary >>= \(ArbitraryTxSignature _ _ sig) -> return sig
-        ArbitraryPubKeyC _ key <- arbitrary
-        return $ ArbitraryPKHashCInput $ RegularInput $
-            SpendPKHash sig $ toPubKeyG key
-
--- | Arbitrary ScriptInput of type SpendMulSig
-newtype ArbitraryMSInput = ArbitraryMSInput ScriptInput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryMSInput where
-    arbitrary = do
-        ArbitraryMSParam m _ <- arbitrary
-        sigs <- vectorOf m f
-        return $ ArbitraryMSInput $ RegularInput $ SpendMulSig sigs
-      where
-        f = arbitrary >>= \(ArbitraryTxSignature _ _ sig) -> return sig
-
--- | Arbitrary ScriptInput of type ScriptHashInput
-newtype ArbitrarySHInput = ArbitrarySHInput ScriptInput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitrarySHInput where
-    arbitrary = do
-        ArbitrarySimpleInput i <- arbitrary
-        ArbitrarySimpleOutput o <- arbitrary
-        return $ ArbitrarySHInput $ ScriptHashInput (getRegularInput i) o
-
--- | Arbitrary ScriptInput of type ScriptHashInput containing a RedeemScript
--- of type PayMulSig and an input of type SpendMulSig. Only compressed keys
--- are used.
-newtype ArbitraryMulSigSHCInput = ArbitraryMulSigSHCInput ScriptInput
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryMulSigSHCInput where
-    arbitrary = do
-        ArbitraryMSCOutput rdm@(PayMulSig _ m) <- arbitrary
-        sigs <- vectorOf m f
-        return $ ArbitraryMulSigSHCInput $ ScriptHashInput (SpendMulSig sigs) rdm
-      where
-        f = arbitrary >>= \(ArbitraryTxSignature _ _ sig) -> return sig
-
diff --git a/Network/Haskoin/Test/Transaction.hs b/Network/Haskoin/Test/Transaction.hs
deleted file mode 100644
--- a/Network/Haskoin/Test/Transaction.hs
+++ /dev/null
@@ -1,292 +0,0 @@
-{-|
-  Arbitrary types for Network.Haskoin.Transaction
--}
-module Network.Haskoin.Test.Transaction
-( ArbitrarySatoshi(..)
-, ArbitraryTx(..)
-, ArbitraryTxHash(..)
-, ArbitraryTxIn(..)
-, ArbitraryTxOut(..)
-, ArbitraryOutPoint(..)
-, ArbitraryAddrOnlyTx(..)
-, ArbitraryAddrOnlyTxIn(..)
-, ArbitraryAddrOnlyTxOut(..)
-, ArbitrarySigInput(..)
-, ArbitraryPKSigInput(..)
-, ArbitraryPKHashSigInput(..)
-, ArbitraryMSSigInput(..)
-, ArbitrarySHSigInput(..)
-, ArbitrarySigningData(..)
-, ArbitraryPartialTxs(..)
-) where
-
-import Test.QuickCheck
-    ( Arbitrary
-    , arbitrary
-    , vectorOf
-    , oneof
-    , choose
-    , elements
-    )
-
-import Control.Monad (forM)
-
-import Data.Word (Word64)
-import Data.List (permutations, nubBy, nub)
-import qualified Data.ByteString as BS (empty)
-
-import Network.Haskoin.Test.Crypto
-import Network.Haskoin.Test.Script
-
-import Network.Haskoin.Transaction
-import Network.Haskoin.Script
-import Network.Haskoin.Crypto
-import Network.Haskoin.Constants
-import Network.Haskoin.Util
-
-newtype ArbitraryTxHash = ArbitraryTxHash TxHash
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryTxHash where
-    arbitrary = do
-        ArbitraryHash256 h <- arbitrary
-        return $ ArbitraryTxHash $ TxHash h
-
--- | Arbitrary amount of Satoshi as Word64 (Between 1 and 21e14)
-newtype ArbitrarySatoshi = ArbitrarySatoshi Word64
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitrarySatoshi where
-    arbitrary = ArbitrarySatoshi <$> choose (1, maxSatoshi)
-
-instance Coin ArbitrarySatoshi where
-    coinValue (ArbitrarySatoshi v) = v
-
--- | Arbitrary OutPoint
-newtype ArbitraryOutPoint = ArbitraryOutPoint OutPoint
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryOutPoint where
-    arbitrary = do
-        op <- do
-            ArbitraryTxHash tx <- arbitrary
-            i  <- arbitrary
-            return $ OutPoint tx i
-        return $ ArbitraryOutPoint op
-
--- | Arbitrary TxOut
-newtype ArbitraryTxOut = ArbitraryTxOut TxOut
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryTxOut where
-    arbitrary = do
-        ArbitrarySatoshi v <- arbitrary
-        ArbitraryScriptOutput out <- arbitrary
-        return $ ArbitraryTxOut $ TxOut v $ encodeOutputBS out
-
--- | Arbitrary TxIn
-newtype ArbitraryTxIn = ArbitraryTxIn TxIn
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryTxIn where
-    arbitrary = do
-        ArbitraryOutPoint o <- arbitrary
-        ArbitraryScriptInput inp <- arbitrary
-        s <- arbitrary
-        return $ ArbitraryTxIn $ TxIn o (encodeInputBS inp) s
-
--- | Arbitrary Tx
-newtype ArbitraryTx = ArbitraryTx Tx
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryTx where
-    arbitrary = do
-        v <- arbitrary
-        ni <- choose (0,5)
-        no <- choose (0,5)
-        inps <- vectorOf ni $ arbitrary >>= \(ArbitraryTxIn i) -> return i
-        outs <- vectorOf no $ arbitrary >>= \(ArbitraryTxOut o) -> return o
-        let uniqueInps = nubBy (\a b -> prevOutput a == prevOutput b) inps
-        t <- arbitrary
-        return $ ArbitraryTx $ createTx v uniqueInps outs t
-
--- | Arbitrary Tx containing only inputs of type SpendPKHash, SpendScriptHash
--- (multisig) and outputs of type PayPKHash and PaySH. Only compressed
--- public keys are used.
-newtype ArbitraryAddrOnlyTx = ArbitraryAddrOnlyTx Tx
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryAddrOnlyTx where
-    arbitrary = do
-        v <- arbitrary
-        ni <- choose (0,5)
-        no <- choose (0,5)
-        inps <- vectorOf ni $
-            arbitrary >>= \(ArbitraryAddrOnlyTxIn i) -> return i
-        outs <- vectorOf no $
-            arbitrary >>= \(ArbitraryAddrOnlyTxOut o) -> return o
-        t <- arbitrary
-        return $ ArbitraryAddrOnlyTx $ createTx v inps outs t
-
--- | Arbitrary TxIn that can only be of type SpendPKHash or
--- SpendScriptHash (multisig). Only compressed public keys are used.
-newtype ArbitraryAddrOnlyTxIn = ArbitraryAddrOnlyTxIn TxIn
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryAddrOnlyTxIn where
-    arbitrary = do
-        ArbitraryOutPoint o <- arbitrary
-        inp <- oneof
-            [ arbitrary >>= \(ArbitraryPKHashCInput i) -> return i
-            , arbitrary >>= \(ArbitraryMulSigSHCInput i) -> return i
-            ]
-        s <- arbitrary
-        return $ ArbitraryAddrOnlyTxIn $ TxIn o (encodeInputBS inp) s
-
--- | Arbitrary TxOut that can only be of type PayPKHash or PaySH
-newtype ArbitraryAddrOnlyTxOut = ArbitraryAddrOnlyTxOut TxOut
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryAddrOnlyTxOut where
-    arbitrary = do
-        ArbitrarySatoshi v <- arbitrary
-        out <- oneof
-            [ arbitrary >>= \(ArbitraryPKHashOutput o) -> return o
-            , arbitrary >>= \(ArbitrarySHOutput o) -> return o
-            ]
-        return $ ArbitraryAddrOnlyTxOut $ TxOut v $ encodeOutputBS out
-
--- | Arbitrary SigInput with the corresponding private keys used
--- to generate the ScriptOutput or RedeemScript
-data ArbitrarySigInput = ArbitrarySigInput SigInput [PrvKey]
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitrarySigInput where
-    arbitrary = do
-        (si, ks) <- oneof
-            [ arbitrary >>= \(ArbitraryPKSigInput si k) -> return (si, [k])
-            , arbitrary >>= \(ArbitraryPKHashSigInput si k) -> return (si, [k])
-            , arbitrary >>= \(ArbitraryMSSigInput si ks) -> return (si, ks)
-            , arbitrary >>= \(ArbitrarySHSigInput si ks) -> return (si, ks)
-            ]
-        return $ ArbitrarySigInput si ks
-
--- | Arbitrary SigInput with a ScriptOutput of type PayPK
-data ArbitraryPKSigInput = ArbitraryPKSigInput SigInput PrvKey
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPKSigInput where
-    arbitrary = do
-        ArbitraryPrvKey k <- arbitrary
-        let out = PayPK $ derivePubKey k
-        ArbitraryOutPoint op <- arbitrary
-        ArbitraryValidSigHash sh <- arbitrary
-        return $ ArbitraryPKSigInput (SigInput out op sh Nothing) k
-
--- | Arbitrary SigInput with a ScriptOutput of type PayPKHash
-data ArbitraryPKHashSigInput = ArbitraryPKHashSigInput SigInput PrvKey
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPKHashSigInput where
-    arbitrary = do
-        ArbitraryPrvKey k <- arbitrary
-        let out = PayPKHash $ pubKeyAddr $ derivePubKey k
-        ArbitraryOutPoint op <- arbitrary
-        ArbitraryValidSigHash sh <- arbitrary
-        return $ ArbitraryPKHashSigInput (SigInput out op sh Nothing) k
-
--- | Arbitrary SigInput with a ScriptOutput of type PayMulSig
-data ArbitraryMSSigInput = ArbitraryMSSigInput SigInput [PrvKey]
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryMSSigInput where
-    arbitrary = do
-        ArbitraryMSParam m n <- arbitrary
-        ks <- map (\(ArbitraryPrvKey k) -> k) <$> vectorOf n arbitrary
-        let out = PayMulSig (map derivePubKey ks) m
-        ArbitraryOutPoint op <- arbitrary
-        ArbitraryValidSigHash sh <- arbitrary
-        perm <- choose (0,n-1)
-        let ksPerm = take m $ permutations ks !! perm
-        return $ ArbitraryMSSigInput (SigInput out op sh Nothing) ksPerm
-
--- | Arbitrary SigInput with  ScriptOutput of type PaySH and a RedeemScript
-data ArbitrarySHSigInput = ArbitrarySHSigInput SigInput [PrvKey]
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitrarySHSigInput where
-    arbitrary = do
-        (rdm, ks, op, sh) <- oneof
-            [ a <$> arbitrary, b <$> arbitrary, c <$> arbitrary ]
-        let out = PayScriptHash $ scriptAddr rdm
-        return $ ArbitrarySHSigInput (SigInput out op sh $ Just rdm) ks
-      where
-        a (ArbitraryPKSigInput (SigInput o op sh _) k) = (o, [k], op, sh)
-        b (ArbitraryPKHashSigInput (SigInput o op sh _) k) = (o, [k], op, sh)
-        c (ArbitraryMSSigInput (SigInput o op sh _) ks) = (o, ks, op, sh)
-
--- | Arbitrary Tx (empty TxIn), SigInputs and PrvKeys that can be passed to
--- signTx or detSignTx to fully sign the Tx.
-data ArbitrarySigningData = ArbitrarySigningData Tx [SigInput] [PrvKey]
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitrarySigningData where
-    arbitrary = do
-        v <- arbitrary
-        ni <- choose (1,5)
-        no <- choose (1,5)
-        sigis <- map f <$> vectorOf ni arbitrary
-        let uSigis = nubBy (\(a,_) (b,_) -> sigDataOP a == sigDataOP b) sigis
-        inps <- forM uSigis $ \(s,_) -> do
-            sq <- arbitrary
-            return $ TxIn (sigDataOP s) BS.empty sq
-        outs <- map (\(ArbitraryTxOut o) -> o) <$> vectorOf no arbitrary
-        l <- arbitrary
-        perm <- choose (0, length inps - 1)
-        let tx   = createTx v (permutations inps !! perm) outs l
-            keys = concat $ map snd uSigis
-        return $ ArbitrarySigningData tx (map fst uSigis) keys
-      where
-        f (ArbitrarySigInput s ks) = (s,ks)
-
-data ArbitraryPartialTxs =
-    ArbitraryPartialTxs [Tx] [(ScriptOutput, OutPoint, Int, Int)]
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryPartialTxs where
-    arbitrary = do
-        tx <- arbitraryEmptyTx
-        res <- forM (map prevOutput $ txIn tx) $ \op -> do
-            (so, rdmM, prvs, m, n) <- arbitraryData
-            txs <- mapM (singleSig so rdmM tx op) prvs
-            return (txs, (so, op, m, n))
-        return $ ArbitraryPartialTxs (concat $ map fst res) (map snd res)
-      where
-        singleSig so rdmM tx op prv = do
-            ArbitraryValidSigHash sh <- arbitrary
-            let sigi = SigInput so op sh rdmM
-            return $ fromRight $ signTx tx [sigi] [prv]
-        arbitraryData = do
-            ArbitraryMSParam m n <- arbitrary
-            nPrv <- choose (m,n)
-            keys <- vectorOf n $
-                (\(ArbitraryPubKey k p) -> (k, p)) <$> arbitrary
-            perm <- choose (0, length keys - 1)
-            let pubKeys = map snd keys
-                prvKeys = take nPrv $ permutations (map fst keys) !! perm
-            let so = PayMulSig pubKeys m
-            elements [ (so, Nothing, prvKeys, m, n)
-                     , (PayScriptHash $ scriptAddr so, Just so, prvKeys, m, n)
-                     ]
-        arbitraryEmptyTx = do
-            v <- arbitrary
-            no <- choose (1,5)
-            ni <- choose (1,5)
-            outs <- vectorOf no $ (\(ArbitraryTxOut o) -> o) <$> arbitrary
-            ops <- vectorOf ni $ (\(ArbitraryOutPoint op) -> op) <$> arbitrary
-            t <- arbitrary
-            s <- arbitrary
-            return $ createTx
-                v (map (\op -> TxIn op BS.empty s) (nub ops)) outs t
-
-
diff --git a/Network/Haskoin/Test/Util.hs b/Network/Haskoin/Test/Util.hs
deleted file mode 100644
--- a/Network/Haskoin/Test/Util.hs
+++ /dev/null
@@ -1,48 +0,0 @@
-module Network.Haskoin.Test.Util
-( ArbitraryByteString(..)
-, ArbitraryNotNullByteString(..)
-, ArbitraryUTCTime(..)
-) where
-
-import Test.QuickCheck
-    ( Arbitrary
-    , Gen
-    , arbitrary
-    , choose
-    , listOf1
-    )
-
-import Data.Word (Word32)
-import Data.Time.Clock (UTCTime(..))
-import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
-import qualified Data.ByteString as BS (ByteString, pack, drop)
-
--- | Arbitrary strict ByteString
-data ArbitraryByteString = ArbitraryByteString BS.ByteString
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryByteString where
-    arbitrary = do
-        bs <- BS.pack `fmap` arbitrary
-        n <- choose (0, 2)
-        -- to give us some with non-0 offset
-        return $ ArbitraryByteString $ BS.drop n bs
-
--- | Arbitrary strict ByteString that is not empty
-data ArbitraryNotNullByteString = ArbitraryNotNullByteString BS.ByteString
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryNotNullByteString where
-    arbitrary = do
-        bs <- BS.pack `fmap` (listOf1 arbitrary)
-        return $ ArbitraryNotNullByteString bs
-
--- | Arbitrary UTCTime that generates dates after 01 Jan 1970 01:00:00 CET
-newtype ArbitraryUTCTime = ArbitraryUTCTime UTCTime
-    deriving (Eq, Show, Read)
-
-instance Arbitrary ArbitraryUTCTime where
-    arbitrary = do
-        w <- (arbitrary :: Gen Word32)
-        return $ ArbitraryUTCTime $ posixSecondsToUTCTime $ realToFrac w
-
diff --git a/Network/Haskoin/Transaction.hs b/Network/Haskoin/Transaction.hs
deleted file mode 100644
--- a/Network/Haskoin/Transaction.hs
+++ /dev/null
@@ -1,50 +0,0 @@
-{-|
-  This package provides functions for building and signing both simple
-  transactions and multisignature transactions.
--}
-module Network.Haskoin.Transaction
-(
-  -- *Transaction Types
-  Tx
-, createTx
-, txVersion
-, txIn
-, txOut
-, txLockTime
-, txHash
-, TxIn(..)
-, TxOut(..)
-, OutPoint(..)
-, TxHash(..)
-, hexToTxHash
-, txHashToHex
-, nosigTxHash
-
-  -- *Build Transactions
-, buildTx
-, buildAddrTx
-
-  -- *Sign Transactions
-, SigInput(..)
-, signTx
-, signInput
-, mergeTxs
-, verifyStdTx
-, verifyStdInput
-
-  -- *Coin selection
-, Coin(..)
-, chooseCoins
-, chooseCoinsSink
-, chooseMSCoins
-, chooseMSCoinsSink
-, guessTxSize
-, getFee
-, getMSFee
-
-, buildInput
-) where
-
-import Network.Haskoin.Transaction.Builder
-import Network.Haskoin.Transaction.Types
-
diff --git a/Network/Haskoin/Transaction/Builder.hs b/Network/Haskoin/Transaction/Builder.hs
deleted file mode 100644
--- a/Network/Haskoin/Transaction/Builder.hs
+++ /dev/null
@@ -1,433 +0,0 @@
-module Network.Haskoin.Transaction.Builder
-( Coin(..)
-, buildTx
-, buildAddrTx
-, SigInput(..)
-, signTx
-, signInput
-, mergeTxs
-, verifyStdTx
-, verifyStdInput
-, guessTxSize
-, chooseCoins
-, chooseCoinsSink
-, chooseMSCoins
-, chooseMSCoinsSink
-, getFee
-, getMSFee
-
-, buildInput
-) where
-
-import           Control.Arrow                     (first)
-import           Control.DeepSeq                   (NFData, rnf)
-import           Control.Monad                     (foldM, mzero, unless)
-import           Control.Monad.Identity            (runIdentity)
-import           Data.Aeson                        (FromJSON, ToJSON,
-                                                    Value (Object), object,
-                                                    parseJSON, toJSON, (.:),
-                                                    (.:?), (.=))
-import           Data.ByteString                   (ByteString)
-import qualified Data.ByteString                   as BS (empty, length, null,
-                                                          replicate)
-import           Data.Conduit                      (Sink, await, ($$))
-import           Data.Conduit.List                 (sourceList)
-import           Data.List                         (find, nub)
-import           Data.Maybe                        (catMaybes, fromJust,
-                                                    fromMaybe, isJust,
-                                                    maybeToList)
-import           Data.Serialize                    (encode)
-import           Data.String.Conversions           (cs)
-import           Data.Word                         (Word64)
-import           Network.Haskoin.Crypto
-import           Network.Haskoin.Node.Types
-import           Network.Haskoin.Script
-import           Network.Haskoin.Transaction.Types
-import           Network.Haskoin.Util
-
--- | Any type can be used as a Coin if it can provide a value in Satoshi.
--- The value is used in coin selection algorithms.
-class Coin c where
-    coinValue :: c -> Word64
-
--- | Coin selection algorithm for normal (non-multisig) transactions. This
--- function returns the selected coins together with the amount of change to
--- send back to yourself, taking the fee into account.
-chooseCoins :: Coin c
-            => Word64 -- ^ Target price to pay.
-            -> Word64 -- ^ Fee price per 1000 bytes.
-            -> Bool   -- ^ Try to find better solution when one is found
-            -> [c]    -- ^ List of ordered coins to choose from.
-            -> Either String ([c], Word64)
-               -- ^ Coin selection result and change amount.
-chooseCoins target kbfee continue coins =
-    runIdentity $ sourceList coins $$ chooseCoinsSink target kbfee continue
-
--- | Coin selection algorithm for normal (non-multisig) transactions. This
--- function returns the selected coins together with the amount of change to
--- send back to yourself, taking the fee into account. This version uses a
--- Sink if you need conduit-based coin selection.
-chooseCoinsSink :: (Monad m, Coin c)
-                => Word64 -- ^ Target price to pay.
-                -> Word64 -- ^ Fee price per 1000 bytes.
-                -> Bool   -- ^ Try to find better solution when one is found
-                -> Sink c m (Either String ([c], Word64))
-                   -- ^ Coin selection result and change amount.
-chooseCoinsSink target kbfee continue
-    | target > 0 =
-        maybeToEither err <$> greedyAddSink target (getFee kbfee) continue
-    | otherwise = return $ Left "chooseCoins: Target must be > 0"
-  where
-    err = "chooseCoins: No solution found"
-
--- | Coin selection algorithm for multisignature transactions. This function
--- returns the selected coins together with the amount of change to send back
--- to yourself, taking the fee into account. This function assumes all the
--- coins are script hash outputs that send funds to a multisignature address.
-chooseMSCoins :: Coin c
-              => Word64     -- ^ Target price to pay.
-              -> Word64     -- ^ Fee price per 1000 bytes.
-              -> (Int, Int) -- ^ Multisig parameters m of n (m,n).
-              -> Bool -- ^ Try to find better solution when one is found
-              -> [c]
-              -> Either String ([c], Word64)
-                 -- ^ Coin selection result and change amount.
-chooseMSCoins target kbfee ms continue coins =
-    runIdentity $ sourceList coins $$ chooseMSCoinsSink target kbfee ms continue
-
--- | Coin selection algorithm for multisignature transactions. This function
--- returns the selected coins together with the amount of change to send back
--- to yourself, taking the fee into account. This function assumes all the
--- coins are script hash outputs that send funds to a multisignature address.
--- This version uses a Sink if you need conduit-based coin selection.
-chooseMSCoinsSink :: (Monad m, Coin c)
-                  => Word64     -- ^ Target price to pay.
-                  -> Word64     -- ^ Fee price per 1000 bytes.
-                  -> (Int, Int) -- ^ Multisig parameters m of n (m,n).
-                  -> Bool -- ^ Try to find better solution when one is found
-                  -> Sink c m (Either String ([c], Word64))
-                     -- ^ Coin selection result and change amount.
-chooseMSCoinsSink target kbfee ms continue
-    | target > 0 =
-        maybeToEither err <$> greedyAddSink target (getMSFee kbfee ms) continue
-    | otherwise = return $ Left "chooseMSCoins: Target must be > 0"
-  where
-    err = "chooseMSCoins: No solution found"
-
--- Select coins greedily by starting from an empty solution. If the continue
--- value is set to True, the algorithm will try to find a better solution in
--- the stream once a solution is found. If the next solution found is not
--- strictly better than the previously found solution, the algorithm stops and
--- returns the previous solution. If the continue value is set to False, the
--- algorithm will return the first solution it finds in the stream.
-greedyAddSink :: (Monad m, Coin c)
-              => Word64          -- ^ Target to reach
-              -> (Int -> Word64) -- ^ Coin count to fee function
-              -> Bool            -- ^ Try to find better solutions
-              -> Sink c m (Maybe ([c], Word64)) -- (Selected coins, change)
-greedyAddSink target fee continue =
-    go [] 0 [] 0
-  where
-    -- The goal is the value we must reach (including the fee) for a certain
-    -- amount of selected coins.
-    goal c = target + fee c
-    go acc aTot ps pTot = await >>= \coinM -> case coinM of
-        -- A coin is available in the stream
-        Just coin -> do
-            let val = coinValue coin
-            -- We have reached the goal using this coin
-            if val + aTot >= (goal $ length acc + 1)
-                -- If we want to continue searching for better solutions
-                then if continue
-                    -- This solution is the first one or
-                    -- This solution is better than the previous one
-                    then if pTot == 0 || val + aTot < pTot
-                        -- Continue searching for better solutions in the stream
-                        then go [] 0 (coin:acc) (val + aTot)
-                        -- Otherwise, we stop here and return the previous
-                        -- solution
-                        else return $ Just (ps, pTot - (goal $ length ps))
-                    -- Otherwise, return this solution
-                    else return $
-                        Just (coin:acc, val + aTot - (goal $ length acc + 1))
-                -- We have not yet reached the goal. Add the coin to the
-                -- accumulator
-                else go (coin:acc) (val + aTot) ps pTot
-        -- We reached the end of the stream
-        Nothing ->
-            return $ if null ps
-                -- If no solution was found, return Nothing
-                then Nothing
-                -- If we have a solution, return it
-                else Just (ps, pTot - (goal $ length ps))
-
-getFee :: Word64 -> Int -> Word64
-getFee kbfee count =
-    kbfee*((len + 999) `div` 1000)
-  where
-    len = fromIntegral $ guessTxSize count [] 2 0
-
-getMSFee :: Word64 -> (Int, Int) -> Int -> Word64
-getMSFee kbfee ms count =
-    kbfee*((len + 999) `div` 1000)
-  where
-    len = fromIntegral $ guessTxSize 0 (replicate count ms) 2 0
-
--- | Computes an upper bound on the size of a transaction based on some known
--- properties of the transaction.
-guessTxSize :: Int         -- ^ Number of regular transaction inputs.
-            -> [(Int,Int)]
-               -- ^ For every multisig input in the transaction, provide
-               -- the multisig parameters m of n (m,n) for that input.
-            -> Int         -- ^ Number of pay to public key hash outputs.
-            -> Int         -- ^ Number of pay to script hash outputs.
-            -> Int         -- ^ Upper bound on the transaction size.
-guessTxSize pki msi pkout msout =
-    8 + inpLen + inp + outLen + out
-  where
-    inpLen = BS.length $ encode $ VarInt $ fromIntegral $ (length msi) + pki
-    outLen = BS.length $ encode $ VarInt $ fromIntegral $ pkout + msout
-    inp    = pki*148 + (sum $ map guessMSSize msi)
-             -- (20: hash160) + (5: opcodes) +
-             -- (1: script len) + (8: Word64)
-    out    = pkout*34 +
-             -- (20: hash160) + (3: opcodes) +
-             -- (1: script len) + (8: Word64)
-             msout*32
-
--- Size of a multisig pay2sh input
-guessMSSize :: (Int,Int) -> Int
-guessMSSize (m,n) =
-    -- OutPoint (36) + Sequence (4) + Script
-    40 + (BS.length $ encode $ VarInt $ fromIntegral scp) + scp
-  where
-    -- OP_M + n*PubKey + OP_N + OP_CHECKMULTISIG
-    rdm = BS.length $ encode $ opPushData $ BS.replicate (n*34 + 3) 0
-    -- Redeem + m*sig + OP_0
-    scp = rdm + m*73 + 1
-
-{- Build a new Tx -}
-
--- | Build a transaction by providing a list of outpoints as inputs
--- and a list of recipients addresses and amounts as outputs.
-buildAddrTx :: [OutPoint] -> [(ByteString, Word64)] -> Either String Tx
-buildAddrTx xs ys =
-    buildTx xs =<< mapM f ys
-  where
-    f (s, v) = case base58ToAddr s of
-        Just a@(PubKeyAddress _) -> return (PayPKHash a,v)
-        Just a@(ScriptAddress _) -> return (PayScriptHash a,v)
-        _ -> Left $ "buildAddrTx: Invalid address " ++ cs s
-
--- | Build a transaction by providing a list of outpoints as inputs
--- and a list of 'ScriptOutput' and amounts as outputs.
-buildTx :: [OutPoint] -> [(ScriptOutput, Word64)] -> Either String Tx
-buildTx xs ys =
-    mapM fo ys >>= \os -> return $ createTx 1 (map fi xs) os 0
-  where
-    fi outPoint = TxIn outPoint BS.empty maxBound
-    fo (o, v)
-        | v <= 2100000000000000 = return $ TxOut v $ encodeOutputBS o
-        | otherwise =
-            Left $ "buildTx: Invalid amount " ++ show v
-
--- | Data type used to specify the signing parameters of a transaction input.
--- To sign an input, the previous output script, outpoint and sighash are
--- required. When signing a pay to script hash output, an additional redeem
--- script is required.
-data SigInput = SigInput
-    { sigDataOut    :: !ScriptOutput -- ^ Output script to spend.
-    , sigDataOP     :: !OutPoint     -- ^ Spending tranasction OutPoint
-    , sigDataSH     :: !SigHash      -- ^ Signature type.
-    , sigDataRedeem :: !(Maybe RedeemScript) -- ^ Redeem script
-    } deriving (Eq, Read, Show)
-
-instance NFData SigInput where
-    rnf (SigInput o p h b) = rnf o `seq` rnf p `seq` rnf h `seq` rnf b
-
-instance ToJSON SigInput where
-    toJSON (SigInput so op sh rdm) = object $
-        [ "pkscript" .= so
-        , "outpoint" .= op
-        , "sighash"  .= sh
-        ] ++ [ "redeem" .= r | r <- maybeToList rdm ]
-
-instance FromJSON SigInput where
-    parseJSON (Object o) = do
-        so  <- o .: "pkscript"
-        op  <- o .: "outpoint"
-        sh  <- o .: "sighash"
-        rdm <- o .:? "redeem"
-        return $ SigInput so op sh rdm
-    parseJSON _ = mzero
-
--- | Sign a transaction by providing the 'SigInput' signing paramters and
--- a list of private keys. The signature is computed deterministically as
--- defined in RFC-6979.
-signTx :: Tx               -- ^ Transaction to sign
-       -> [SigInput]       -- ^ SigInput signing parameters
-       -> [PrvKey]         -- ^ List of private keys to use for signing
-       -> Either String Tx -- ^ Signed transaction
-signTx otx sigis allKeys
-    | null ti   = Left "signTx: Transaction has no inputs"
-    | otherwise = foldM go otx $ findSigInput sigis ti
-  where
-    ti = txIn otx
-    go tx (sigi@(SigInput so _ _ rdmM), i) = do
-        keys <- sigKeys so rdmM allKeys
-        foldM (\t k -> signInput t i sigi k) tx keys
-
--- | Sign a single input in a transaction deterministically (RFC-6979).
-signInput :: Tx -> Int -> SigInput -> PrvKey -> Either String Tx
-signInput tx i (SigInput so _ sh rdmM) key = do
-    let sig = TxSignature (signMsg msg key) sh
-    si <- buildInput tx i so rdmM sig $ derivePubKey key
-    let ins = updateIndex i (txIn tx) (f si)
-    return $ createTx (txVersion tx) ins (txOut tx) (txLockTime tx)
-  where
-    f si x = x{ scriptInput = encodeInputBS si }
-    msg = txSigHash tx (encodeOutput $ fromMaybe so rdmM) i sh
-
--- Order the SigInput with respect to the transaction inputs. This allow the
--- users to provide the SigInput in any order. Users can also provide only a
--- partial set of SigInputs.
-findSigInput :: [SigInput] -> [TxIn] -> [(SigInput, Int)]
-findSigInput si ti =
-    catMaybes $ map g $ zip (matchTemplate si ti f) [0..]
-  where
-    f s txin = sigDataOP s == prevOutput txin
-    g (Just s, i)  = Just (s,i)
-    g (Nothing, _) = Nothing
-
--- Find from the list of private keys which one is required to sign the
--- provided ScriptOutput.
-sigKeys :: ScriptOutput -> (Maybe RedeemScript) -> [PrvKey]
-        -> Either String [PrvKey]
-sigKeys so rdmM keys = do
-    case (so, rdmM) of
-        (PayPK p, Nothing) -> return $
-            map fst $ maybeToList $ find ((== p) . snd) zipKeys
-        (PayPKHash a, Nothing) -> return $
-            map fst $ maybeToList $ find ((== a) . pubKeyAddr . snd) zipKeys
-        (PayMulSig ps r, Nothing) -> return $
-            map fst $ take r $ filter ((`elem` ps) . snd) zipKeys
-        (PayScriptHash _, Just rdm) ->
-            sigKeys rdm Nothing keys
-        _ -> Left "sigKeys: Could not decode output script"
-  where
-    zipKeys = zip keys (map derivePubKey keys)
-
--- Construct an input, given a signature and a public key
-buildInput :: Tx -> Int -> ScriptOutput -> (Maybe RedeemScript)
-           -> TxSignature -> PubKey -> Either String ScriptInput
-buildInput tx i so rdmM sig pub = case (so, rdmM) of
-    (PayPK _, Nothing) ->
-        return $ RegularInput $ SpendPK sig
-    (PayPKHash _, Nothing) ->
-        return $ RegularInput $ SpendPKHash sig pub
-    (PayMulSig msPubs r, Nothing) -> do
-        let mSigs = take r $ catMaybes $ matchTemplate allSigs msPubs f
-        return $ RegularInput $ SpendMulSig mSigs
-    (PayScriptHash _, Just rdm) -> do
-        inp  <- buildInput tx i rdm Nothing sig pub
-        return $ ScriptHashInput (getRegularInput inp) rdm
-    _ -> Left "buildInput: Invalid output/redeem script combination"
-  where
-    scp     = scriptInput $ txIn tx !! i
-    allSigs = nub $ sig : case decodeInputBS scp of
-        Right (ScriptHashInput (SpendMulSig xs) _) -> xs
-        Right (RegularInput    (SpendMulSig xs))   -> xs
-        _ -> []
-    out = encodeOutput so
-    f (TxSignature x sh) p = verifySig (txSigHash tx out i sh) x p
-
-{- Merge multisig transactions -}
-
-mergeTxs :: [Tx] -> [(ScriptOutput, OutPoint)] -> Either String Tx
-mergeTxs txs os
-    | null txs = error "Transaction list is empty"
-    | length (nub emptyTxs) /= 1 = Left "Transactions do not match"
-    | length txs == 1 = return $ head txs
-    | otherwise = foldM (mergeTxInput txs) (head emptyTxs) outs
-  where
-    zipOp = zip (matchTemplate os (txIn $ head txs) f) [0..]
-    outs = map (first $ fst . fromJust) $ filter (isJust . fst) zipOp
-    f (_,o) txin = o == prevOutput txin
-    emptyTxs = map (\tx -> foldl clearInput tx outs) txs
-    ins is i = updateIndex i is (\ti -> ti{ scriptInput = BS.empty })
-    clearInput tx (_, i) =
-        createTx (txVersion tx) (ins (txIn tx) i) (txOut tx) (txLockTime tx)
-
-mergeTxInput :: [Tx] -> Tx -> (ScriptOutput, Int) -> Either String Tx
-mergeTxInput txs tx (so, i) = do
-    -- Ignore transactions with empty inputs
-    let ins = map (scriptInput . (!! i) . txIn) txs
-    sigRes <- mapM extractSigs $ filter (not . BS.null) ins
-    let rdm = snd $ head sigRes
-    unless (all (== rdm) $ map snd sigRes) $
-        Left "Redeem scripts do not match"
-    si <- encodeInputBS <$> go (nub $ concat $ map fst sigRes) so rdm
-    let ins' = updateIndex i (txIn tx) (\ti -> ti{ scriptInput = si })
-    return $ createTx (txVersion tx) ins' (txOut tx) (txLockTime tx)
-  where
-    go allSigs out rdmM = case out of
-        PayMulSig msPubs r ->
-            let sigs = take r $ catMaybes $ matchTemplate allSigs msPubs $ f out
-            in return $ RegularInput $ SpendMulSig sigs
-        PayScriptHash _ -> case rdmM of
-            Just rdm -> do
-                si <- go allSigs rdm Nothing
-                return $ ScriptHashInput (getRegularInput si) rdm
-            _ -> Left "Invalid output script type"
-        _ -> Left "Invalid output script type"
-    extractSigs si = case decodeInputBS si of
-        Right (RegularInput (SpendMulSig sigs)) -> Right (sigs, Nothing)
-        Right (ScriptHashInput (SpendMulSig sigs) rdm) -> Right (sigs, Just rdm)
-        _ -> Left "Invalid script input type"
-    f out (TxSignature x sh) p =
-        verifySig (txSigHash tx (encodeOutput out) i sh) x p
-
-{- Tx verification -}
-
--- | Verify if a transaction is valid and all of its inputs are standard.
-verifyStdTx :: Tx -> [(ScriptOutput, OutPoint)] -> Bool
-verifyStdTx tx xs =
-    all go $ zip (matchTemplate xs (txIn tx) f) [0..]
-  where
-    f (_,o) txin        = o == prevOutput txin
-    go (Just (so,_), i) = verifyStdInput tx i so
-    go _                = False
-
--- | Verify if a transaction input is valid and standard.
-verifyStdInput :: Tx -> Int -> ScriptOutput -> Bool
-verifyStdInput tx i so' =
-    go (scriptInput $ txIn tx !! i) so'
-  where
-    go inp so = case decodeInputBS inp of
-        Right (RegularInput (SpendPK (TxSignature sig sh))) ->
-            let pub = getOutputPubKey so
-            in  verifySig (txSigHash tx out i sh) sig pub
-        Right (RegularInput (SpendPKHash (TxSignature sig sh) pub)) ->
-            let a = getOutputAddress so
-            in pubKeyAddr pub == a &&
-                verifySig (txSigHash tx out i sh) sig pub
-        Right (RegularInput (SpendMulSig sigs)) ->
-            let pubs = getOutputMulSigKeys so
-                r    = getOutputMulSigRequired so
-            in  countMulSig tx out i pubs sigs == r
-        Right (ScriptHashInput si rdm) ->
-            scriptAddr rdm == getOutputAddress so &&
-            go (encodeInputBS $ RegularInput si) rdm
-        _ -> False
-      where
-        out = encodeOutput so
-
--- Count the number of valid signatures
-countMulSig :: Tx -> Script -> Int -> [PubKey] -> [TxSignature] -> Int
-countMulSig _ _ _ [] _  = 0
-countMulSig _ _ _ _  [] = 0
-countMulSig tx out i (pub:pubs) sigs@(TxSignature sig sh:rest)
-    | verifySig (txSigHash tx out i sh) sig pub =
-         1 + countMulSig tx out i pubs rest
-    | otherwise = countMulSig tx out i pubs sigs
-
diff --git a/Network/Haskoin/Transaction/Types.hs b/Network/Haskoin/Transaction/Types.hs
deleted file mode 100644
--- a/Network/Haskoin/Transaction/Types.hs
+++ /dev/null
@@ -1,277 +0,0 @@
-module Network.Haskoin.Transaction.Types
-( Tx
-, createTx
-, txVersion
-, txIn
-, txOut
-, txLockTime
-, txHash
-, TxIn(..)
-, TxOut(..)
-, OutPoint(..)
-, TxHash(..)
-, hexToTxHash
-, txHashToHex
-, nosigTxHash
-) where
-
-import Control.DeepSeq (NFData, rnf)
-import Control.Monad (liftM2, replicateM, forM_, mzero, (<=<))
-
-import Data.Aeson (Value(String), FromJSON, ToJSON, parseJSON, toJSON, withText)
-import Data.Word (Word32, Word64)
-import Data.Serialize (Serialize, get, put, encode)
-import Data.Serialize.Get
-    ( getWord32le
-    , getWord64le
-    , getByteString
-    , remaining
-    , lookAhead
-    )
-import Data.Serialize.Put
-    ( putWord32le
-    , putWord64le
-    , putByteString
-    )
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as BS
-    ( length
-    , empty
-    , reverse
-    )
-import Data.Maybe (fromMaybe)
-import Data.String (IsString, fromString)
-import Data.String.Conversions (cs)
-import Text.Read (readPrec, parens, lexP, pfail)
-import qualified Text.Read as Read (Lexeme(Ident, String))
-import Network.Haskoin.Util
-import Network.Haskoin.Crypto.Hash
-import Network.Haskoin.Node.Types
-
-newtype TxHash = TxHash { getTxHash :: Hash256 }
-    deriving (Eq, Ord)
-
-instance NFData TxHash where
-    rnf  = rnf . getHash256 . getTxHash
-
-instance Read TxHash where
-    readPrec = parens $ do
-        Read.Ident "TxHash" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ hexToTxHash $ cs str
-
-instance Show TxHash where
-    showsPrec d h = showParen (d > 10) $
-        showString "TxHash " . shows (txHashToHex h)
-
-instance IsString TxHash where
-    fromString =
-        TxHash . fromMaybe e . bsToHash256
-               . BS.reverse . fromMaybe e' . decodeHex . cs
-      where
-        e = error "Could not read transaction hash from decoded hex string"
-        e' = error "Colud not decode hex string with transaction hash"
-
-instance Serialize TxHash where
-    get = TxHash <$> get
-    put = put . getTxHash
-
-nosigTxHash :: Tx -> TxHash
-nosigTxHash tx =
-    TxHash $ doubleHash256 $ encode tx{ _txIn = map clearInput $ txIn tx }
-  where
-    clearInput ti = ti{ scriptInput = BS.empty }
-
-txHashToHex :: TxHash -> ByteString
-txHashToHex (TxHash h) = encodeHex $ BS.reverse $ getHash256 h
-
-hexToTxHash :: ByteString -> Maybe TxHash
-hexToTxHash hex = do
-    bs <- BS.reverse <$> decodeHex hex
-    h <- bsToHash256 bs
-    return $ TxHash h
-
-instance FromJSON TxHash where
-    parseJSON = withText "Transaction id" $ \t ->
-        maybe mzero return $ hexToTxHash $ cs t
-
-instance ToJSON TxHash where
-    toJSON = String . cs . txHashToHex
-
--- | Data type representing a bitcoin transaction
-data Tx = Tx
-    { -- | Transaction data format version
-      _txVersion  :: !Word32
-      -- | List of transaction inputs
-    , _txIn       :: ![TxIn]
-      -- | List of transaction outputs
-    , _txOut      :: ![TxOut]
-      -- | The block number of timestamp at which this transaction is locked
-    , _txLockTime :: !Word32
-     -- | Hash of the transaction
-    , _txHash     :: !TxHash
-    } deriving (Eq)
-
-txVersion :: Tx -> Word32
-txVersion = _txVersion
-
-txIn :: Tx -> [TxIn]
-txIn = _txIn
-
-txOut :: Tx -> [TxOut]
-txOut = _txOut
-
-txLockTime :: Tx -> Word32
-txLockTime = _txLockTime
-
-txHash :: Tx -> TxHash
-txHash = _txHash
-
-createTx :: Word32 -> [TxIn] -> [TxOut] -> Word32 -> Tx
-createTx v is os l =
-    Tx { _txVersion  = v
-       , _txIn       = is
-       , _txOut      = os
-       , _txLockTime = l
-       , _txHash     = TxHash $ doubleHash256 $ encode tx
-       }
-  where
-    tx = Tx { _txVersion  = v
-            , _txIn       = is
-            , _txOut      = os
-            , _txLockTime = l
-            , _txHash     = fromString $ replicate 64 '0'
-            }
-
-instance Show Tx where
-    showsPrec d tx = showParen (d > 10) $
-        showString "Tx " . shows (encodeHex $ encode tx)
-
-instance Read Tx where
-    readPrec = parens $ do
-        Read.Ident "Tx" <- lexP
-        Read.String str <- lexP
-        maybe pfail return $ decodeToMaybe =<< decodeHex (cs str)
-
-instance IsString Tx where
-    fromString =
-        fromMaybe e . (decodeToMaybe <=< decodeHex) . cs
-      where
-        e = error "Could not read transaction from hex string"
-
-instance NFData Tx where
-    rnf (Tx v i o l t) = rnf v `seq` rnf i `seq` rnf o `seq` rnf l `seq` rnf t
-
-instance Serialize Tx where
-    get = do
-        start <- remaining
-        (v, is, os, l, end) <- lookAhead $ do
-            v  <- getWord32le
-            is <- replicateList =<< get
-            os <- replicateList =<< get
-            l  <- getWord32le
-            end <- remaining
-            return (v, is, os, l, end)
-        bs <- getByteString $ fromIntegral $ start - end
-        return $ Tx { _txVersion  = v
-                    , _txIn       = is
-                    , _txOut      = os
-                    , _txLockTime = l
-                    , _txHash     = TxHash $ doubleHash256 bs
-                    }
-      where
-        replicateList (VarInt c) = replicateM (fromIntegral c) get
-
-    put (Tx v is os l _) = do
-        putWord32le v
-        put $ VarInt $ fromIntegral $ length is
-        forM_ is put
-        put $ VarInt $ fromIntegral $ length os
-        forM_ os put
-        putWord32le l
-
-instance FromJSON Tx where
-    parseJSON = withText "Tx" $
-        maybe mzero return . (decodeToMaybe <=< decodeHex) . cs
-
-instance ToJSON Tx where
-    toJSON = String . cs . encodeHex . encode
-
--- | Data type representing a transaction input.
-data TxIn =
-    TxIn {
-           -- | Reference the previous transaction output (hash + position)
-           prevOutput   :: !OutPoint
-           -- | Script providing the requirements of the previous transaction
-           -- output to spend those coins.
-         , scriptInput  :: !ByteString
-           -- | Transaction version as defined by the sender of the
-           -- transaction. The intended use is for replacing transactions with
-           -- new information before the transaction is included in a block.
-         , txInSequence :: !Word32
-         } deriving (Eq, Show, Read)
-
-instance NFData TxIn where
-    rnf (TxIn p i s) = rnf p `seq` rnf i `seq` rnf s
-
-instance Serialize TxIn where
-    get =
-        TxIn <$> get <*> (readBS =<< get) <*> getWord32le
-      where
-        readBS (VarInt len) = getByteString $ fromIntegral len
-
-    put (TxIn o s q) = do
-        put o
-        put $ VarInt $ fromIntegral $ BS.length s
-        putByteString s
-        putWord32le q
-
--- | Data type representing a transaction output.
-data TxOut =
-    TxOut {
-            -- | Transaction output value.
-            outValue     :: !Word64
-            -- | Script specifying the conditions to spend this output.
-          , scriptOutput :: !ByteString
-          } deriving (Eq, Show, Read)
-
-instance NFData TxOut where
-    rnf (TxOut v o) = rnf v `seq` rnf o
-
-instance Serialize TxOut where
-    get = do
-        val <- getWord64le
-        (VarInt len) <- get
-        TxOut val <$> (getByteString $ fromIntegral len)
-
-    put (TxOut o s) = do
-        putWord64le o
-        put $ VarInt $ fromIntegral $ BS.length s
-        putByteString s
-
--- | The OutPoint is used inside a transaction input to reference the previous
--- transaction output that it is spending.
-data OutPoint = OutPoint
-    { -- | The hash of the referenced transaction.
-      outPointHash  :: !TxHash
-      -- | The position of the specific output in the transaction.
-      -- The first output position is 0.
-    , outPointIndex :: !Word32
-    } deriving (Read, Show, Eq)
-
-instance NFData OutPoint where
-    rnf (OutPoint h i) = rnf h `seq` rnf i
-
-instance FromJSON OutPoint where
-    parseJSON = withText "OutPoint" $
-        maybe mzero return . (decodeToMaybe <=< decodeHex) . cs
-
-instance ToJSON OutPoint where
-    toJSON = String . cs . encodeHex . encode
-
-instance Serialize OutPoint where
-    get = do
-        (h,i) <- liftM2 (,) get getWord32le
-        return $ OutPoint h i
-    put (OutPoint h i) = put h >> putWord32le i
-
diff --git a/Network/Haskoin/Util.hs b/Network/Haskoin/Util.hs
deleted file mode 100644
--- a/Network/Haskoin/Util.hs
+++ /dev/null
@@ -1,187 +0,0 @@
-{-|
-  This module defines various utility functions used across the
-  Network.Haskoin modules.
--}
-module Network.Haskoin.Util
-(
-  -- * ByteString helpers
-  bsToInteger
-, integerToBS
-, encodeHex
-, decodeHex
-
-  -- * Maybe and Either monad helpers
-, isLeft
-, isRight
-, fromRight
-, fromLeft
-, eitherToMaybe
-, maybeToEither
-, liftEither
-, liftMaybe
-
-  -- * Various helpers
-, decodeToMaybe
-, updateIndex
-, matchTemplate
-
-  -- * Triples
-, fst3
-, snd3
-, lst3
-
-  -- * MonadState
-, modify'
-
-  -- * JSON Utilities
-, dropFieldLabel
-, dropSumLabels
-
-) where
-
-import Control.Monad (guard)
-import Control.Monad.Trans.Either (EitherT, hoistEither)
-import Control.Monad.State (MonadState, get, put)
-
-import Data.Serialize (Serialize, decode)
-import Data.Word (Word8)
-import Data.Bits ((.|.), shiftL, shiftR)
-import Data.Char (toLower)
-import Data.Aeson.Types
-    (Options(..), SumEncoding(..), defaultOptions, defaultTaggedObject)
-
-import Data.ByteString (ByteString)
-import qualified Data.ByteString.Base16 as B16
-import qualified Data.ByteString as BS
-    (pack, empty, foldr', reverse, unfoldr)
-
--- ByteString helpers
-
--- | Decode a big endian Integer from a bytestring.
-bsToInteger :: ByteString -> Integer
-bsToInteger = BS.foldr' f 0 . BS.reverse
-  where
-    f w n = toInteger w .|. shiftL n 8
-
--- | Encode an Integer to a bytestring as big endian
-integerToBS :: Integer -> ByteString
-integerToBS 0 = BS.pack [0]
-integerToBS i
-    | i > 0     = BS.reverse $ BS.unfoldr f i
-    | otherwise = error "integerToBS not defined for negative values"
-  where
-    f 0 = Nothing
-    f x = Just (fromInteger x :: Word8, x `shiftR` 8)
-
-encodeHex :: ByteString -> ByteString
-encodeHex = B16.encode
-
--- | Decode hexadecimal 'ByteString'. This function can fail if the string
--- contains invalid hexadecimal (0-9, a-f, A-F) characters
-decodeHex :: ByteString -> Maybe ByteString
-decodeHex bs =
-    let (x, b) = B16.decode bs
-    in guard (b == BS.empty) >> return x
-
--- Maybe and Either monad helpers
-
--- | Returns 'True' if the 'Either' value is 'Right'
-isRight :: Either a b -> Bool
-isRight (Right _) = True
-isRight _         = False
-
--- | Returns 'True' if the 'Either' value is 'Left'
-isLeft :: Either a b -> Bool
-isLeft = not . isRight
-
--- | Extract the 'Right' value from an 'Either' value. Fails if the value is
--- 'Left'
-fromRight :: Either a b -> b
-fromRight (Right b) = b
-fromRight _ = error "Either.fromRight: Left"
-
--- | Extract the 'Left' value from an 'Either' value. Fails if the value is 'Right'
-fromLeft :: Either a b -> a
-fromLeft (Left a) = a
-fromLeft _ = error "Either.fromLeft: Right"
-
--- | Transforms an 'Either' value into a 'Maybe' value. 'Right' is mapped to 'Just'
--- and 'Left' is mapped to 'Nothing'. The value inside 'Left' is lost.
-eitherToMaybe :: Either a b -> Maybe b
-eitherToMaybe (Right b) = Just b
-eitherToMaybe _ = Nothing
-
--- | Transforms a 'Maybe' value into an 'Either' value. 'Just' is mapped to
--- 'Right' and 'Nothing' is mapped to 'Left'. You also pass in an error value
--- in case 'Left' is returned.
-maybeToEither :: b -> Maybe a -> Either b a
-maybeToEither err = maybe (Left err) Right
-
--- | Lift a 'Either' computation into the 'EitherT' monad
-liftEither :: Monad m => Either b a -> EitherT b m a
-liftEither = hoistEither
-
--- | Lift a 'Maybe' computation into the 'EitherT' monad
-liftMaybe :: Monad m => b -> Maybe a -> EitherT b m a
-liftMaybe err = liftEither . maybeToEither err
-
--- Various helpers
-
--- Helper function to decode Data.Serialize into Maybe
-decodeToMaybe :: Serialize a => ByteString -> Maybe a
-decodeToMaybe bs = eitherToMaybe $ decode bs
-
--- | Applies a function to only one element of a list defined by its index.  If
--- the index is out of the bounds of the list, the original list is returned.
-updateIndex :: Int      -- ^ The index of the element to change
-            -> [a]      -- ^ The list of elements
-            -> (a -> a) -- ^ The function to apply
-            -> [a]      -- ^ The result with one element changed
-updateIndex i xs f
-    | i < 0 || i >= length xs = xs
-    | otherwise = l ++ (f h : r)
-  where
-    (l,h:r) = splitAt i xs
-
--- | Use the list @[b]@ as a template and try to match the elements of @[a]@
--- against it. For each element of @[b]@ return the (first) matching element of
--- @[a]@, or 'Nothing'. Output list has same size as @[b]@ and contains results
--- in same order. Elements of @[a]@ can only appear once.
-matchTemplate :: [a]              -- ^ The input list
-              -> [b]              -- ^ The list to serve as a template
-              -> (a -> b -> Bool) -- ^ The comparison function
-              -> [Maybe a]        -- ^ Results of the template matching
-matchTemplate [] bs _ = replicate (length bs) Nothing
-matchTemplate _  [] _ = []
-matchTemplate as (b:bs) f = case break (`f` b) as of
-    (l,r:rs) -> Just r  : matchTemplate (l ++ rs) bs f
-    _        -> Nothing : matchTemplate as bs f
-
--- | Returns the first value of a triple.
-fst3 :: (a,b,c) -> a
-fst3 (a,_,_) = a
-
--- | Returns the second value of a triple.
-snd3 :: (a,b,c) -> b
-snd3 (_,b,_) = b
-
--- | Returns the last value of a triple.
-lst3 :: (a,b,c) -> c
-lst3 (_,_,c) = c
-
--- | Strict evaluation of the new state
-modify' :: MonadState s m => (s -> s) -> m ()
-modify' f = get >>= \x -> put $! f x
-
-dropFieldLabel :: Int -> Options
-dropFieldLabel n = defaultOptions
-    { fieldLabelModifier = map toLower . drop n
-    , omitNothingFields  = False -- TODO: aeson issue #293 prompted this
-    }
-
-dropSumLabels :: Int -> Int -> String -> Options
-dropSumLabels c f tag = (dropFieldLabel f)
-    { constructorTagModifier = map toLower . drop c
-    , sumEncoding = defaultTaggedObject { tagFieldName = tag }
-    }
-
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,16 @@
+# Haskoin Core
+
+Haskoin Core is a library of Bitcoin and Bitcoin Cash functions written in Haskell featuring:
+
+- Hashing functions (SHA-256, RIPEMD-160)
+- Base58 support
+- CashAddr support
+- Bech32 suport
+- BIP32 extended key derivation and parsing (m/1'/2/3)
+- BIP39 mnemonic keys
+- ECDSA secp256k1 cryptographic primitives
+- Script parsing
+- Building and signing of standard transactions (regular, multisig, p2sh)
+- Parsing and manipulation of all Bitcoin and Bitcoin Cash protocol messages
+- Bloom filters and partial merkle trees (used in SPV wallets)
+- Comprehensive test suite
diff --git a/data/forkid_script_tests.json b/data/forkid_script_tests.json
new file mode 100644
--- /dev/null
+++ b/data/forkid_script_tests.json
@@ -0,0 +1,32 @@
+[
+[
+    [
+        123450.00000000
+    ],
+    "0x47 0x30440220368d68340dfbebf99d5ec87d77fba899763e466c0a7ab2fa0221fb868ab0f3ef0220266c1a52a8e5b7b597613b80cf53814d3925dfb6715dce712c8e7a25e63a044041",
+    "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+    "SIGHASH_FORKID",
+    "OK",
+    "P2PK FORKID"
+],
+[
+    [
+        123450.00000000
+    ],
+    "0x47 0x3044022053cebf0befa1f435d1631d7b0de2c870203b4cedcce98bd2ce6b72e08978e1a302203b63345ec2de3682eec5f008a3b1c925b2f71be53f0469a49fb7f1df0c49409b41",
+    "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+    "SIGHASH_FORKID",
+    "EVAL_FALSE",
+    "P2PK INVALID AMOUNT"
+],
+[
+    [
+        123450.00000000
+    ],
+    "0x47 0x30440220368d68340dfbebf99d5ec87d77fba899763e466c0a7ab2fa0221fb868ab0f3ef0220266c1a52a8e5b7b597613b80cf53814d3925dfb6715dce712c8e7a25e63a044041",
+    "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+    "STRICTENC",
+    "OK",
+    "Works only on a forkid network"
+]
+]
diff --git a/data/forkid_sighash.json b/data/forkid_sighash.json
new file mode 100644
--- /dev/null
+++ b/data/forkid_sighash.json
@@ -0,0 +1,16 @@
+[
+    ["raw_transaction, script, input_index, value, hashType, signature_hash (result)"],
+    ["0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f0000000000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac11000000", "76a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac", 1, 600000000, 1, "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670"],
+    ["0100000001db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a54770100000000feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac92040000", "76a91479091972186c449eb1ded22b78e40d009bdf008988ac", 0, 1000000000, 1, "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6"],
+    ["0100000002fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e0000000000ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac00000000", "21026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac", 1, 4900000000, 3, "82dde6e4f1e94d02c2b7ad03d2115d691f48d064e9d52f58194a6637e4194391"],
+    ["0100000002fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e0000000000ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac00000000", "210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac", 1, 4900000000, 3, "fef7bd749cce710c5c052bd796df1af0d935e59cea63736268bcbe2d2134fc47"],
+    ["0100000002e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac00000000", "0063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac", 0, 16777215, 131, "e9071e75e25b8a1e298a72f0d2e9f4f95a0f5cdf86a533cda597eb402ed13b3a"],
+    ["0100000002e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac00000000", "68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac", 1, 16777215, 131, "cd72f1f1a433ee9df816857fad88d8ebd97e09a75cd481583eb841c330275e54"],
+    ["010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000", "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae", 0, 987654321, 1, "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c"],
+    ["010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000", "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae", 0, 987654321, 2, "e9733bc60ea13c95c6527066bb975a2ff29a925e80aa14c213f686cbae5d2f36"],
+    ["010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000", "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae", 0, 987654321, 3, "1e1f1c303dc025bd664acb72e583e933fae4cff9148bf78c157d1e8f78530aea"],
+    ["010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000", "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae", 0, 987654321, 129, "2a67f03e63a6a422125878b40b82da593be8d4efaafe88ee528af6e5a9955c6e"],
+    ["010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000", "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae", 0, 987654321, 130, "781ba15f3779d5542ce8ecb5c18716733a5ee42a6f51488ec96154934e2c890a"],
+    ["010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000", "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae", 0, 987654321, 131, "511e8e52ed574121fc1b654970395502128263f62662e076dc6baf05c2e6a99b"],
+    ["010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f14c1d000000ffffffff0101000000000000000000000000", "ad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01", 0, 200000, 1, "71c9cd9b2869b9c70b01b1f0360c148f42dee72297db312638df136f43311f23"]
+]
diff --git a/data/script_tests.json b/data/script_tests.json
new file mode 100644
--- /dev/null
+++ b/data/script_tests.json
@@ -0,0 +1,608 @@
+[
+["Automatically generated test cases"],
+[
+    "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+    "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+    "",
+    "OK",
+    "P2PK"
+],
+[
+    "0x47 0x304402200a5c6163f07b8c3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+    "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+    "",
+    "EVAL_FALSE",
+    "P2PK, bad sig"
+],
+[
+    "0x47 0x304402206e05a6fe23c59196ffe176c9ddc31e73a9885638f9d1328d47c0c703863b8876022076feb53811aa5b04e0e79f938eb19906cc5e67548bc555a8e8b8b0fc603d840c01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508",
+    "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG",
+    "",
+    "OK",
+    "P2PKH"
+],
+[
+    "0x47 0x3044022034bb0494b50b8ef130e2185bb220265b9284ef5b4b8a8da4d8415df489c83b5102206259a26d9cc0a125ac26af6153b17c02956855ebe1467412f066e402f5f05d1201 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
+    "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG",
+    "",
+    "EQUALVERIFY",
+    "P2PKH, bad pubkey"
+],
+[
+    "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281",
+    "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+    "",
+    "OK",
+    "P2PK anyonecanpay"
+],
+[
+    "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201",
+    "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+    "",
+    "EVAL_FALSE",
+    "P2PK anyonecanpay marked with normal hashtype"
+],
+[
+    "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+    "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
+    "P2SH",
+    "OK",
+    "P2SH(P2PK)"
+],
+[
+    "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+    "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
+    "P2SH",
+    "EVAL_FALSE",
+    "P2SH(P2PK), bad redeemscript"
+],
+[
+    "0x47 0x30440220781ba4f59a7b207a10db87628bc2168df4d59b844b397d2dbc9a5835fb2f2b7602206ed8fbcc1072fe2dfc5bb25909269e5dc42ffcae7ec2bc81d59692210ff30c2b01 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x19 0x76a91491b24bf9f5288532960ac687abb035127b1d28a588ac",
+    "HASH160 0x14 0x7f67f0521934a57d3039f77f9f32cf313f3ac74b EQUAL",
+    "P2SH",
+    "OK",
+    "P2SH(P2PKH)"
+],
+[
+    "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
+    "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
+    "DISABLED (haskoin does only full P2SH validation)",
+    "OK",
+    "P2SH(P2PKH), bad sig but no VERIFY_P2SH"
+],
+[
+    "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
+    "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
+    "P2SH",
+    "EQUALVERIFY",
+    "P2SH(P2PKH), bad sig"
+],
+[
+    "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+    "",
+    "OK",
+    "3-of-3"
+],
+[
+    "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0",
+    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+    "",
+    "EVAL_FALSE",
+    "3-of-3, 2 sigs"
+],
+[
+    "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x30440220563e5b3b1fc11662a84bc5ea2a32cc3819703254060ba30d639a1aaf2d5068ad0220601c1f47ddc76d93284dd9ed68f7c9974c4a0ea7cbe8a247d6bc3878567a5fca01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
+    "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
+    "P2SH",
+    "OK",
+    "P2SH(2-of-3)"
+],
+[
+    "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
+    "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
+    "P2SH",
+    "EVAL_FALSE",
+    "P2SH(2-of-3), 1 sig"
+],
+[
+    "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "DISABLED",
+    "NONSTRICT",
+    "P2PK with too much R padding but no DERSIG"
+],
+[
+    "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "DERSIG",
+    "SIG_DER",
+    "P2PK with too much R padding"
+],
+[
+    "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "",
+    "NONSTRICT",
+    "P2PK with too much S padding but no DERSIG"
+],
+[
+    "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "DERSIG",
+    "SIG_DER",
+    "P2PK with too much S padding"
+],
+[
+    "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "",
+    "NONSTRICT",
+    "P2PK with too little R padding but no DERSIG"
+],
+[
+    "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "DERSIG",
+    "SIG_DER",
+    "P2PK with too little R padding"
+],
+[
+    "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+    "",
+    "NONSTRICT",
+    "P2PK NOT with bad sig with too much R padding but no DERSIG"
+],
+[
+    "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+    "DERSIG, DISABLED (haskoin can not parse non-standard scripts)",
+    "SIG_DER",
+    "P2PK NOT with bad sig with too much R padding"
+],
+[
+    "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "EVAL_FALSE",
+    "P2PK NOT with too much R padding but no DERSIG"
+],
+[
+    "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+    "DERSIG, DISABLED (haskoin can not parse non-standard scripts)",
+    "SIG_DER",
+    "P2PK NOT with too much R padding"
+],
+[
+    "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "",
+    "NONSTRICT",
+    "BIP66 example 1, without DERSIG"
+],
+[
+    "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "DERSIG",
+    "SIG_DER",
+    "BIP66 example 1, with DERSIG"
+],
+[
+    "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "EVAL_FALSE",
+    "BIP66 example 2, without DERSIG"
+],
+[
+    "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+    "DERSIG, DISABLED (haskoin can not parse non-standard scripts)",
+    "SIG_DER",
+    "BIP66 example 2, with DERSIG"
+],
+[
+    "0",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "",
+    "EVAL_FALSE",
+    "BIP66 example 3, without DERSIG"
+],
+[
+    "0",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "DERSIG",
+    "EVAL_FALSE",
+    "BIP66 example 3, with DERSIG"
+],
+[
+    "0",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "BIP66 example 4, without DERSIG"
+],
+[
+    "0",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+    "DERSIG, DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "BIP66 example 4, with DERSIG"
+],
+[
+    "0x09 0x300602010102010101",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+    "DERSIG, DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "BIP66 example 4, with DERSIG, non-null DER-compliant signature"
+],
+[
+    "0",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+    "DERSIG,NULLFAIL,DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "BIP66 example 4, with DERSIG and NULLFAIL"
+],
+[
+    "0x09 0x300602010102010101",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+    "DERSIG,NULLFAIL,DISABLED (haskoin can not parse non-standard scripts)",
+    "NULLFAIL",
+    "BIP66 example 4, with DERSIG and NULLFAIL, non-null DER-compliant signature"
+],
+[
+    "1",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "",
+    "EVAL_FALSE",
+    "BIP66 example 5, without DERSIG"
+],
+[
+    "1",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+    "DERSIG",
+    "SIG_DER",
+    "BIP66 example 5, with DERSIG"
+],
+[
+    "1",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "BIP66 example 6, without DERSIG"
+],
+[
+    "1",
+    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+    "DERSIG,DISABLED (haskoin can not parse non-standard scripts)",
+    "SIG_DER",
+    "BIP66 example 6, with DERSIG"
+],
+[
+    "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+    "",
+    "NONSTRICT",
+    "BIP66 example 7, without DERSIG"
+],
+[
+    "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+    "DERSIG",
+    "SIG_DER",
+    "BIP66 example 7, with DERSIG"
+],
+[
+    "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "EVAL_FALSE",
+    "BIP66 example 8, without DERSIG"
+],
+[
+    "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+    "DERSIG,DISABLED (haskoin can not parse non-standard scripts)",
+    "SIG_DER",
+    "BIP66 example 8, with DERSIG"
+],
+[
+    "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+    "",
+    "EVAL_FALSE",
+    "BIP66 example 9, without DERSIG"
+],
+[
+    "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+    "DERSIG",
+    "SIG_DER",
+    "BIP66 example 9, with DERSIG"
+],
+[
+    "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "BIP66 example 10, without DERSIG"
+],
+[
+    "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+    "DERSIG,DISABLED (haskoin can not parse non-standard scripts)",
+    "SIG_DER",
+    "BIP66 example 10, with DERSIG"
+],
+[
+    "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+    "",
+    "EVAL_FALSE",
+    "BIP66 example 11, without DERSIG"
+],
+[
+    "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+    "DERSIG",
+    "EVAL_FALSE",
+    "BIP66 example 11, with DERSIG"
+],
+[
+    "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "BIP66 example 12, without DERSIG"
+],
+[
+    "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+    "DERSIG,DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "BIP66 example 12, with DERSIG"
+],
+[
+    "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101",
+    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+    "",
+    "NONSTRICT",
+    "P2PK with multi-byte hashtype, without DERSIG"
+],
+[
+    "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101",
+    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+    "DERSIG",
+    "SIG_DER",
+    "P2PK with multi-byte hashtype, with DERSIG"
+],
+[
+    "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001",
+    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+    "",
+    "NONSTRICT",
+    "P2PK with high S but no LOW_S"
+],
+[
+    "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001",
+    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+    "LOW_S, DISABLED (haskoin does not check LOW_S decoding)",
+    "SIG_HIGH_S",
+    "P2PK with high S"
+],
+[
+    "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
+    "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+    "DISABLED (haskoin can not parse hybrid pubkeys)",
+    "OK",
+    "P2PK with hybrid pubkey but no STRICTENC"
+],
+[
+    "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
+    "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+    "STRICTENC,DISABLED (haskoin can not parse hybrid pubkeys)",
+    "PUBKEYTYPE",
+    "P2PK with hybrid pubkey"
+],
+[
+    "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+    "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "EVAL_FALSE",
+    "P2PK NOT with hybrid pubkey but no STRICTENC"
+],
+[
+    "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+    "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+    "STRICTENC,DISABLED (haskoin can not parse non-standard scripts)",
+    "PUBKEYTYPE",
+    "P2PK NOT with hybrid pubkey"
+],
+[
+    "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+    "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "P2PK NOT with invalid hybrid pubkey but no STRICTENC"
+],
+[
+    "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+    "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+    "STRICTENC,DISABLED (haskoin can not parse non-standard scripts)",
+    "PUBKEYTYPE",
+    "P2PK NOT with invalid hybrid pubkey"
+],
+[
+    "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401",
+    "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+    "DISABLED (haskoin can not parse hybrid pubkeys)",
+    "OK",
+    "1-of-2 with the second 1 hybrid pubkey and no STRICTENC"
+],
+[
+    "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401",
+    "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+    "STRICTENC,DISABLED (haskoin can not parse hybrid pubkeys)",
+    "OK",
+    "1-of-2 with the second 1 hybrid pubkey"
+],
+[
+    "0 0x47 0x3044022079c7824d6c868e0e1a273484e28c2654a27d043c8a27f49f52cb72efed0759090220452bbbf7089574fa082095a4fc1b3a16bafcf97a3a34d745fafc922cce66b27201",
+    "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG",
+    "STRICTENC,DISABLED (haskoin can not parse hybrid pubkeys)",
+    "PUBKEYTYPE",
+    "1-of-2 with the first 1 hybrid pubkey"
+],
+[
+    "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
+    "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+    "",
+    "NONSTRICT",
+    "P2PK with undefined hashtype but no STRICTENC"
+],
+[
+    "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
+    "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+    "STRICTENC",
+    "SIG_HASHTYPE",
+    "P2PK with undefined hashtype"
+],
+[
+    "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
+    "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC"
+],
+[
+    "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
+    "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
+    "STRICTENC,DISABLED (haskoin can not parse non-standard scripts)",
+    "SIG_HASHTYPE",
+    "P2PK NOT with invalid sig and undefined hashtype"
+],
+[
+    "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+    "",
+    "NONSTRICT",
+    "3-of-3 with nonzero dummy but no NULLDUMMY"
+],
+[
+    "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+    "NULLDUMMY",
+    "SIG_NULLDUMMY",
+    "3-of-3 with nonzero dummy"
+],
+[
+    "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01",
+    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
+    "DISABLED (haskoin can not parse non-standard scripts)",
+    "OK",
+    "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY"
+],
+[
+    "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01",
+    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
+    "NULLDUMMY,DISABLED (haskoin can not parse non-standard scripts)",
+    "SIG_NULLDUMMY",
+    "3-of-3 NOT with invalid sig with nonzero dummy"
+],
+[
+    "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+    "DISABLED (haskoin can not parse non-standard inputs)",
+    "OK",
+    "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY"
+],
+[
+    "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+    "SIGPUSHONLY",
+    "SIG_PUSHONLY",
+    "2-of-2 with two identical keys and sigs pushed using OP_DUP"
+],
+[
+    "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+    "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
+    "DISABLED (haskoin can not parse non-standard inputs)",
+    "OK",
+    "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY"
+],
+[
+    "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 NOP8",
+    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+    "DISABLED (haskoin can not parse non-standard inputs)",
+    "OK",
+    "P2PK with non-push scriptSig but with P2SH validation"
+],
+[
+    "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+    "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
+    "P2SH,DISABLED (haskoin can not parse non-standard inputs)",
+    "SIG_PUSHONLY",
+    "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY"
+],
+[
+    "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+    "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
+    "SIGPUSHONLY,DISABLED (haskoin can not parse non-standard inputs)",
+    "SIG_PUSHONLY",
+    "P2SH(P2PK) with non-push scriptSig but not P2SH"
+],
+[
+    "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901",
+    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+    "SIGPUSHONLY",
+    "OK",
+    "2-of-2 with two identical keys and sigs pushed"
+],
+[
+    "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+    "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+    "P2SH, DISABLED (haskoin does not parse non-standard inputs)",
+    "OK",
+    "P2PK with unnecessary input but no CLEANSTACK"
+],
+[
+    "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+    "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+    "CLEANSTACK,P2SH",
+    "CLEANSTACK",
+    "P2PK with unnecessary input"
+],
+[
+    "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+    "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
+    "P2SH, DISABLED (haskoin does not parse non-standard inputs)",
+    "OK",
+    "P2SH with unnecessary input but no CLEANSTACK"
+],
+[
+    "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+    "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
+    "CLEANSTACK,P2SH",
+    "CLEANSTACK",
+    "P2SH with unnecessary input"
+],
+[
+    "0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+    "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
+    "CLEANSTACK,P2SH",
+    "OK",
+    "P2SH with CLEANSTACK"
+],
+[
+    [
+        123450.00000000
+    ],
+    "0x47 0x30440220368d68340dfbebf99d5ec87d77fba899763e466c0a7ab2fa0221fb868ab0f3ef0220266c1a52a8e5b7b597613b80cf53814d3925dfb6715dce712c8e7a25e63a044041",
+    "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+    "STRICTENC",
+    "ILLEGAL_FORKID",
+    "P2PK INVALID FORKID"
+]
+]
diff --git a/data/sig_nonstrict.json b/data/sig_nonstrict.json
new file mode 100644
--- /dev/null
+++ b/data/sig_nonstrict.json
@@ -0,0 +1,24 @@
+[
+    "non-hex strings are ignored",
+
+    "too short:",    "30050201FF020001",
+    "too long:",     "30470221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105022200002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+    "hashtype:",     "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed11",
+    "type:",         "314402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+    "total length:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+    "S len oob:",    "301F01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb101",
+    "R+S:",          "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed0001",
+
+    "R type:",       "304401205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+    "R len = 0:",    "3024020002202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+    "R<0:",          "304402208990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+    "R padded:",     "30450221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+
+
+    "S type:",       "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610501202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+    "S len = 0:",    "302402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105020001",
+    "S<0:",          "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050220fd5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+    "S padded:",     "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050221002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+    "High S:",       "30450220076045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba01",
+    "High S:",       "3046022100876045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba01"
+]
diff --git a/data/sig_strict.json b/data/sig_strict.json
new file mode 100644
--- /dev/null
+++ b/data/sig_strict.json
@@ -0,0 +1,5 @@
+[
+    "300602010102010101",
+    "3008020200ff020200ff01",
+    "304402203932c892e2e550f3af8ee4ce9c215a87f9bb831dcac87b2838e2c2eaa891df0c022030b61dd36543125d56b9f9f3a1f9353189e5af33cdda8d77a5209aec03978fa001"
+]
diff --git a/data/sighash.json b/data/sighash.json
new file mode 100644
--- /dev/null
+++ b/data/sighash.json
@@ -0,0 +1,503 @@
+[
+	["raw_transaction, script, input_index, hashType, signature_hash (result)"],
+	["907c2bc503ade11cc3b04eb2918b6f547b0630ab569273824748c87ea14b0696526c66ba740200000004ab65ababfd1f9bdd4ef073c7afc4ae00da8a66f429c917a0081ad1e1dabce28d373eab81d8628de802000000096aab5253ab52000052ad042b5f25efb33beec9f3364e8a9139e8439d9d7e26529c3c30b6c3fd89f8684cfd68ea0200000009ab53526500636a52ab599ac2fe02a526ed040000000008535300516352515164370e010000000003006300ab2ec229", "", 2, 1864164639, "31af167a6cf3f9d5f6875caa4d31704ceb0eba078d132b78dab52c3b8997317e"],
+	["a0aa3126041621a6dea5b800141aa696daf28408959dfb2df96095db9fa425ad3f427f2f6103000000015360290e9c6063fa26912c2e7fb6a0ad80f1c5fea1771d42f12976092e7a85a4229fdb6e890000000001abc109f6e47688ac0e4682988785744602b8c87228fcef0695085edf19088af1a9db126e93000000000665516aac536affffffff8fe53e0806e12dfd05d67ac68f4768fdbe23fc48ace22a5aa8ba04c96d58e2750300000009ac51abac63ab5153650524aa680455ce7b000000000000499e50030000000008636a00ac526563ac5051ee030000000003abacabd2b6fe000000000003516563910fb6b5", "65", 0, -1391424484, "48d6a1bd2cd9eec54eb866fc71209418a950402b5d7e52363bfb75c98e141175"],
+	["6e7e9d4b04ce17afa1e8546b627bb8d89a6a7fefd9d892ec8a192d79c2ceafc01694a6a7e7030000000953ac6a51006353636a33bced1544f797f08ceed02f108da22cd24c9e7809a446c61eb3895914508ac91f07053a01000000055163ab516affffffff11dc54eee8f9e4ff0bcf6b1a1a35b1cd10d63389571375501af7444073bcec3c02000000046aab53514a821f0ce3956e235f71e4c69d91abe1e93fb703bd33039ac567249ed339bf0ba0883ef300000000090063ab65000065ac654bec3cc504bcf499020000000005ab6a52abac64eb060100000000076a6a5351650053bbbc130100000000056a6aab53abd6e1380100000000026a51c4e509b8", "acab655151", 0, 479279909, "2a3d95b09237b72034b23f2d2bb29fa32a58ab5c6aa72f6aafdfa178ab1dd01c"],
+	["73107cbd025c22ebc8c3e0a47b2a760739216a528de8d4dab5d45cbeb3051cebae73b01ca10200000007ab6353656a636affffffffe26816dffc670841e6a6c8c61c586da401df1261a330a6c6b3dd9f9a0789bc9e000000000800ac6552ac6aac51ffffffff0174a8f0010000000004ac52515100000000", "5163ac63635151ac", 1, 1190874345, "06e328de263a87b09beabe222a21627a6ea5c7f560030da31610c4611f4a46bc"],
+	["e93bbf6902be872933cb987fc26ba0f914fcfc2f6ce555258554dd9939d12032a8536c8802030000000453ac5353eabb6451e074e6fef9de211347d6a45900ea5aaf2636ef7967f565dce66fa451805c5cd10000000003525253ffffffff047dc3e6020000000007516565ac656aabec9eea010000000001633e46e600000000000015080a030000000001ab00000000", "5300ac6a53ab6a", 1, -886562767, "f03aa4fc5f97e826323d0daa03343ebf8a34ed67a1ce18631f8b88e5c992e798"],
+	["50818f4c01b464538b1e7e7f5ae4ed96ad23c68c830e78da9a845bc19b5c3b0b20bb82e5e9030000000763526a63655352ffffffff023b3f9c040000000008630051516a6a5163a83caf01000000000553ab65510000000000", "6aac", 0, 946795545, "746306f322de2b4b58ffe7faae83f6a72433c22f88062cdde881d4dd8a5a4e2d"],
+	["a93e93440250f97012d466a6cc24839f572def241c814fe6ae94442cf58ea33eb0fdd9bcc1030000000600636a0065acffffffff5dee3a6e7e5ad6310dea3e5b3ddda1a56bf8de7d3b75889fc024b5e233ec10f80300000007ac53635253ab53ffffffff0160468b04000000000800526a5300ac526a00000000", "ac00636a53", 1, 1773442520, "5c9d3a2ce9365bb72cfabbaa4579c843bb8abf200944612cf8ae4b56a908bcbd"],
+	["ce7d371f0476dda8b811d4bf3b64d5f86204725deeaa3937861869d5b2766ea7d17c57e40b0100000003535265ffffffff7e7e9188f76c34a46d0bbe856bde5cb32f089a07a70ea96e15e92abb37e479a10100000006ab6552ab655225bcab06d1c2896709f364b1e372814d842c9c671356a1aa5ca4e060462c65ae55acc02d0000000006abac0063ac5281b33e332f96beebdbc6a379ebe6aea36af115c067461eb99d22ba1afbf59462b59ae0bd0200000004ab635365be15c23801724a1704000000000965006a65ac00000052ca555572", "53ab530051ab", 1, 2030598449, "c336b2f7d3702fbbdeffc014d106c69e3413c7c71e436ba7562d8a7a2871f181"],
+	["d3b7421e011f4de0f1cea9ba7458bf3486bee722519efab711a963fa8c100970cf7488b7bb0200000003525352dcd61b300148be5d05000000000000000000", "535251536aac536a", 0, -1960128125, "29aa6d2d752d3310eba20442770ad345b7f6a35f96161ede5f07b33e92053e2a"],
+	["04bac8c5033460235919a9c63c42b2db884c7c8f2ed8fcd69ff683a0a2cccd9796346a04050200000003655351fcad3a2c5a7cbadeb4ec7acc9836c3f5c3e776e5c566220f7f965cf194f8ef98efb5e3530200000007526a006552526526a2f55ba5f69699ece76692552b399ba908301907c5763d28a15b08581b23179cb01eac03000000075363ab6a516351073942c2025aa98a05000000000765006aabac65abd7ffa6030000000004516a655200000000", "53ac6365ac526a", 1, 764174870, "bf5fdc314ded2372a0ad078568d76c5064bf2affbde0764c335009e56634481b"],
+	["c363a70c01ab174230bbe4afe0c3efa2d7f2feaf179431359adedccf30d1f69efe0c86ed390200000002ab51558648fe0231318b04000000000151662170000000000008ac5300006a63acac00000000", "", 0, 2146479410, "191ab180b0d753763671717d051f138d4866b7cb0d1d4811472e64de595d2c70"],
+	["8d437a7304d8772210a923fd81187c425fc28c17a5052571501db05c7e89b11448b36618cd02000000026a6340fec14ad2c9298fde1477f1e8325e5747b61b7e2ff2a549f3d132689560ab6c45dd43c3010000000963ac00ac000051516a447ed907a7efffebeb103988bf5f947fc688aab2c6a7914f48238cf92c337fad4a79348102000000085352ac526a5152517436edf2d80e3ef06725227c970a816b25d0b58d2cd3c187a7af2cea66d6b27ba69bf33a0300000007000063ab526553f3f0d6140386815d030000000003ab6300de138f00000000000900525153515265abac1f87040300000000036aac6500000000", "51", 3, -315779667, "b6632ac53578a741ae8c36d8b69e79f39b89913a2c781cdf1bf47a8c29d997a5"],
+	["fd878840031e82fdbe1ad1d745d1185622b0060ac56638290ec4f66b1beef4450817114a2c0000000009516a63ab53650051abffffffff37b7a10322b5418bfd64fb09cd8a27ddf57731aeb1f1f920ffde7cb2dfb6cdb70300000008536a5365ac53515369ecc034f1594690dbe189094dc816d6d57ea75917de764cbf8eccce4632cbabe7e116cd0100000003515352ffffffff035777fc000000000003515200abe9140300000000050063005165bed6d10200000000076300536363ab65195e9110", "635265", 0, 1729787658, "6e3735d37a4b28c45919543aabcb732e7a3e1874db5315abb7cc6b143d62ff10"],
+	["f40a750702af06efff3ea68e5d56e42bc41cdb8b6065c98f1221fe04a325a898cb61f3d7ee030000000363acacffffffffb5788174aef79788716f96af779d7959147a0c2e0e5bfb6c2dba2df5b4b97894030000000965510065535163ac6affffffff0445e6fd0200000000096aac536365526a526aa6546b000000000008acab656a6552535141a0fd010000000000c897ea030000000008526500ab526a6a631b39dba3", "00abab5163ac", 1, -1778064747, "d76d0fc0abfa72d646df888bce08db957e627f72962647016eeae5a8412354cf"],
+	["a63bc673049c75211aa2c09ecc38e360eaa571435fedd2af1116b5c1fa3d0629c269ecccbf0000000008ac65ab516352ac52ffffffffbf1a76fdda7f451a5f0baff0f9ccd0fe9136444c094bb8c544b1af0fa2774b06010000000463535253ffffffff13d6b7c3ddceef255d680d87181e100864eeb11a5bb6a3528cb0d70d7ee2bbbc02000000056a0052abab951241809623313b198bb520645c15ec96bfcc74a2b0f3db7ad61d455cc32db04afc5cc702000000016309c9ae25014d9473020000000004abab6aac3bb1e803", "", 3, -232881718, "6e48f3da3a4ac07eb4043a232df9f84e110485d7c7669dd114f679c27d15b97e"],
+	["4c565efe04e7d32bac03ae358d63140c1cfe95de15e30c5b84f31bb0b65bb542d637f49e0f010000000551abab536348ae32b31c7d3132030a510a1b1aacf7b7c3f19ce8dc49944ef93e5fa5fe2d356b4a73a00100000009abac635163ac00ab514c8bc57b6b844e04555c0a4f4fb426df139475cd2396ae418bc7015820e852f711519bc202000000086a00510000abac52488ff4aec72cbcfcc98759c58e20a8d2d9725aa4a80f83964e69bc4e793a4ff25cd75dc701000000086a52ac6aac5351532ec6b10802463e0200000000000553005265523e08680100000000002f39a6b0", "", 3, 70712784, "c6076b6a45e6fcfba14d3df47a34f6aadbacfba107e95621d8d7c9c0e40518ed"],
+	["1233d5e703403b3b8b4dae84510ddfc126b4838dcb47d3b23df815c0b3a07b55bf3098110e010000000163c5c55528041f480f40cf68a8762d6ed3efe2bd402795d5233e5d94bf5ddee71665144898030000000965525165655151656affffffff6381667e78bb74d0880625993bec0ea3bd41396f2bcccc3cc097b240e5e92d6a01000000096363acac6a63536365ffffffff04610ad60200000000065251ab65ab52e90d680200000000046351516ae30e98010000000008abab52520063656a671856010000000004ac6aac514c84e383", "6aabab636300", 1, -114996813, "aeb8c5a62e8a0b572c28f2029db32854c0b614dbecef0eaa726abebb42eebb8d"],
+	["0c69702103b25ceaed43122cc2672de84a3b9aa49872f2a5bb458e19a52f8cc75973abb9f102000000055365656aacffffffff3ffb1cf0f76d9e3397de0942038c856b0ebbea355dc9d8f2b06036e19044b0450100000000ffffffff4b7793f4169617c54b734f2cd905ed65f1ce3d396ecd15b6c426a677186ca0620200000008655263526551006a181a25b703240cce0100000000046352ab53dee22903000000000865526a6a516a51005e121602000000000852ab52ababac655200000000", "6a516aab63", 1, -2040012771, "a6e6cb69f409ec14e10dd476f39167c29e586e99bfac93a37ed2c230fcc1dbbe"],
+	["fd22692802db8ae6ab095aeae3867305a954278f7c076c542f0344b2591789e7e33e4d29f4020000000151ffffffffb9409129cfed9d3226f3b6bab7a2c83f99f48d039100eeb5796f00903b0e5e5e0100000006656552ac63abd226abac0403e649000000000007abab51ac5100ac8035f10000000000095165006a63526a52510d42db030000000007635365ac6a63ab24ef5901000000000453ab6a0000000000", "536a52516aac6a", 1, 309309168, "7ca0f75e6530ec9f80d031fc3513ca4ecd67f20cb38b4dacc6a1d825c3cdbfdb"],
+	["a43f85f701ffa54a3cc57177510f3ea28ecb6db0d4431fc79171cad708a6054f6e5b4f89170000000008ac6a006a536551652bebeaa2013e779c05000000000665ac5363635100000000", "ac", 0, 2028978692, "58294f0d7f2e68fe1fd30c01764fe1619bcc7961d68968944a0e263af6550437"],
+	["c2b0b99001acfecf7da736de0ffaef8134a9676811602a6299ba5a2563a23bb09e8cbedf9300000000026300ffffffff042997c50300000000045252536a272437030000000007655353ab6363ac663752030000000002ab6a6d5c900000000000066a6a5265abab00000000", "52ac525163515251", 0, -894181723, "8b300032a1915a4ac05cea2f7d44c26f2a08d109a71602636f15866563eaafdc"],
+	["82f9f10304c17a9d954cf3380db817814a8c738d2c811f0412284b2c791ec75515f38c4f8c020000000265ab5729ca7db1b79abee66c8a757221f29280d0681355cb522149525f36da760548dbd7080a0100000001510b477bd9ce9ad5bb81c0306273a3a7d051e053f04ecf3a1dbeda543e20601a5755c0cfae030000000451ac656affffffff71141a04134f6c292c2e0d415e6705dfd8dcee892b0d0807828d5aeb7d11f5ef0300000001520b6c6dc802a6f3dd0000000000056aab515163bfb6800300000000015300000000", "", 3, -635779440, "d55ed1e6c53510f2608716c12132a11fb5e662ec67421a513c074537eeccc34b"],
+	["8edcf5a1014b604e53f0d12fe143cf4284f86dc79a634a9f17d7e9f8725f7beb95e8ffcd2403000000046aabac52ffffffff01c402b5040000000005ab6a63525100000000", "6351525251acabab6a", 0, 1520147826, "2765bbdcd3ebb8b1a316c04656b28d637f80bffbe9b040661481d3dc83eea6d6"],
+	["2074bad5011847f14df5ea7b4afd80cd56b02b99634893c6e3d5aaad41ca7c8ee8e5098df003000000026a6affffffff018ad59700000000000900ac656a526551635300000000", "65635265", 0, -1804671183, "663c999a52288c9999bff36c9da2f8b78d5c61b8347538f76c164ccba9868d0a"],
+	["7100b11302e554d4ef249ee416e7510a485e43b2ba4b8812d8fe5529fe33ea75f36d392c4403000000020000ffffffff3d01a37e075e9a7715a657ae1bdf1e44b46e236ad16fd2f4c74eb9bf370368810000000007636553ac536365ffffffff01db696a0400000000065200ac656aac00000000", "63005151", 0, -1210499507, "b9c3aee8515a4a3b439de1ffc9c156824bda12cb75bfe5bc863164e8fd31bd7a"],
+	["02c1017802091d1cb08fec512db7b012fe4220d57a5f15f9e7676358b012786e1209bcff950100000004acab6352ffffffff799bc282724a970a6fea1828984d0aeb0f16b67776fa213cbdc4838a2f1961a3010000000951516a536552ab6aabffffffff016c7b4b03000000000865abac5253ac5352b70195ad", "65655200516a", 0, -241626954, "be567cb47170b34ff81c66c1142cb9d27f9b6898a384d6dfc4fce16b75b6cb14"],
+	["cb3178520136cd294568b83bb2520f78fecc507898f4a2db2674560d72fd69b9858f75b3b502000000066aac00515100ffffffff03ab005a01000000000563526363006e3836030000000001abfbda3200000000000665ab0065006500000000", "ab516a0063006a5300", 0, 1182109299, "2149e79c3f4513da4e4378608e497dcfdfc7f27c21a826868f728abd2b8a637a"],
+	["18a4b0c004702cf0e39686ac98aab78ad788308f1d484b1ddfe70dc1997148ba0e28515c310300000000ffffffff05275a52a23c59da91129093364e275da5616c4070d8a05b96df5a2080ef259500000000096aac51656a6aac53ab66e64966b3b36a07dd2bb40242dd4a3743d3026e7e1e0d9e9e18f11d068464b989661321030000000265ac383339c4fae63379cafb63b0bab2eca70e1f5fc7d857eb5c88ccd6c0465093924bba8b2a000000000300636ab5e0545402bc2c4c010000000000cd41c002000000000000000000", "abac635253656a00", 3, 2052372230, "32db877b6b1ca556c9e859442329406f0f8246706522369839979a9f7a235a32"],
+	["1d9c5df20139904c582285e1ea63dec934251c0f9cf5c47e86abfb2b394ebc57417a81f67c010000000353515222ba722504800d3402000000000353656a3c0b4a0200000000000fb8d20500000000076300ab005200516462f30400000000015200000000", "ab65", 0, -210854112, "edf73e2396694e58f6b619f68595b0c1cdcb56a9b3147845b6d6afdb5a80b736"],
+	["4504cb1904c7a4acf375ddae431a74de72d5436efc73312cf8e9921f431267ea6852f9714a01000000066a656a656553a2fbd587c098b3a1c5bd1d6480f730a0d6d9b537966e20efc0e352d971576d0f87df0d6d01000000016321aeec3c4dcc819f1290edb463a737118f39ab5765800547522708c425306ebfca3f396603000000055300ac656a1d09281d05bfac57b5eb17eb3fa81ffcedfbcd3a917f1be0985c944d473d2c34d245eb350300000007656a51525152ac263078d9032f470f0500000000066aac00000052e12da60200000000003488410200000000076365006300ab539981e432", "52536a52526a", 1, -31909119, "f0a2deee7fd8a3a9fad6927e763ded11c940ee47e9e6d410f94fda5001f82e0c"],
+	["14bc7c3e03322ec0f1311f4327e93059c996275302554473104f3f7b46ca179bfac9ef753503000000016affffffff9d405eaeffa1ca54d9a05441a296e5cc3a3e32bb8307afaf167f7b57190b07e00300000008abab51ab5263abab45533aa242c61bca90dd15d46079a0ab0841d85df67b29ba87f2393cd764a6997c372b55030000000452005263ffffffff0250f40e02000000000651516a0063630e95ab0000000000046a5151ac00000000", "6a65005151", 0, -1460947095, "aa418d096929394c9147be8818d8c9dafe6d105945ab9cd7ec682df537b5dd79"],
+	["2b3bd0dd04a1832f893bf49a776cd567ec4b43945934f4786b615d6cb850dfc0349b33301a000000000565ac000051cf80c670f6ddafab63411adb4d91a69c11d9ac588898cbfb4cb16061821cc104325c895103000000025163ffffffffa9e2d7506d2d7d53b882bd377bbcc941f7a0f23fd15d2edbef3cd9df8a4c39d10200000009ac63006a52526a5265ffffffff44c099cdf10b10ce87d4b38658d002fd6ea17ae4a970053c05401d86d6e75f99000000000963ab53526a5252ab63ffffffff035af69c01000000000100ba9b8b0400000000004cead10500000000026a520b77d667", "ab52abac526553", 3, -1955078165, "eb9ceecc3b401224cb79a44d23aa8f428e29f1405daf69b4e01910b848ef1523"],
+	["35df11f004a48ba439aba878fe9df20cc935b4a761c262b1b707e6f2b33e2bb7565cd68b130000000000ffffffffb2a2f99abf64163bb57ca900500b863f40c02632dfd9ea2590854c5fb4811da90200000006ac006363636affffffffaf9d89b2a8d2670ca37c8f7c140600b81259f2e037cb4590578ec6e37af8bf200000000005abac6a655270a4751eb551f058a93301ffeda2e252b6614a1fdd0e283e1d9fe53c96c5bbaafaac57b8030000000153ffffffff020d9f3b02000000000100ed7008030000000004abac000000000000", "abac", 3, 593793071, "88fdee1c2d4aeead71d62396e28dc4d00e5a23498eea66844b9f5d26d1f21042"],
+	["a08ff466049fb7619e25502ec22fedfb229eaa1fe275aa0b5a23154b318441bf547989d0510000000005ab5363636affffffff2b0e335cb5383886751cdbd993dc0720817745a6b1c9b8ab3d15547fc9aafd03000000000965656a536a52656a532b53d10584c290d3ac1ab74ab0a19201a4a039cb59dc58719821c024f6bf2eb26322b33f010000000965ac6aac0053ab6353ffffffff048decba6ebbd2db81e416e39dde1f821ba69329725e702bcdea20c5cc0ecc6402000000086363ab5351ac6551466e377b0468c0fa00000000000651ab53ac6a513461c6010000000008636a636365535100eeb3dc010000000006526a52ac516a43f362010000000005000063536500000000", "0063516a", 1, -1158911348, "f6a1ecb50bd7c2594ebecea5a1aa23c905087553e40486dade793c2f127fdfae"],
+	["5ac2f17d03bc902e2bac2469907ec7d01a62b5729340bc58c343b7145b66e6b97d434b30fa000000000163ffffffff44028aa674192caa0d0b4ebfeb969c284cb16b80c312d096efd80c6c6b094cca000000000763acabac516a52ffffffff10c809106e04b10f9b43085855521270fb48ab579266e7474657c6c625062d2d030000000351636595a0a97004a1b69603000000000465ab005352ad68010000000008636a5263acac5100da7105010000000002acab90325200000000000000000000", "6a6aab516a63526353", 2, 1518400956, "f7efb74b1dcc49d316b49c632301bc46f98d333c427e55338be60c7ef0d953be"],
+	["aeb2e11902dc3770c218b97f0b1960d6ee70459ecb6a95eff3f05295dc1ef4a0884f10ba460300000005516352526393e9b1b3e6ae834102d699ddd3845a1e159aa7cf7635edb5c02003f7830fee3788b795f20100000009ab006a526553ac006ad8809c570469290e0400000000050000abab00b10fd5040000000008ab655263abac53ab630b180300000000009d9993040000000002516300000000", "5351ababac6a65", 0, 1084852870, "f2286001af0b0170cbdad92693d0a5ebaa8262a4a9d66e002f6d79a8c94026d1"],
+	["9860ca9a0294ff4812534def8c3a3e3db35b817e1a2ddb7f0bf673f70eab71bb79e90a2f3100000000086a636551acac5165ffffffffed4d6d3cd9ff9b2d490e0c089739121161a1445844c3e204296816ab06e0a83702000000035100ac88d0db5201c3b59a050000000005ac6a0051ab00000000", "535263ab006a526aab", 1, -962088116, "30df2473e1403e2b8e637e576825f785528d998af127d501556e5f7f5ed89a2a"],
+	["4ddaa680026ec4d8060640304b86823f1ac760c260cef81d85bd847952863d629a3002b54b0200000008526365636a656aab65457861fc6c24bdc760c8b2e906b6656edaf9ed22b5f50e1fb29ec076ceadd9e8ebcb6b000000000152ffffffff033ff04f00000000000551526a00657a1d900300000000002153af040000000003006a6300000000", "ab526a53acabab", 0, 1055317633, "7f21b62267ed52462e371a917eb3542569a4049b9dfca2de3c75872b39510b26"],
+	["01e76dcd02ad54cbc8c71d68eaf3fa7c883b65d74217b30ba81f1f5144ef80b706c0dc82ca000000000352ab6a078ec18bcd0514825feced2e8b8ea1ccb34429fae41c70cc0b73a2799e85603613c6870002000000086363ab6365536a53ffffffff043acea90000000000016ad20e1803000000000100fa00830200000000056352515351e864ee00000000000865535253ab6a6551d0c46672", "6a6365abacab", 0, -1420559003, "8af0b4cbdbc011be848edf4dbd2cde96f0578d662cfebc42252495387114224a"],
+	["fa00b26402670b97906203434aa967ce1559d9bd097d56dbe760469e6032e7ab61accb54160100000006635163630052fffffffffe0d3f4f0f808fd9cfb162e9f0c004601acf725cd7ea5683bbdc9a9a433ef15a0200000005ab52536563d09c7bef049040f305000000000153a7c7b9020000000004ac63ab52847a2503000000000553ab00655390ed80010000000005006553ab52860671d4", "536565ab52", 0, 799022412, "40ed8e7bbbd893e15f3cce210ae02c97669818de5946ca37eefc7541116e2c78"],
+	["cb5c06dc01b022ee6105ba410f0eb12b9ce5b5aa185b28532492d839a10cef33d06134b91b010000000153ffffffff02cec0530400000000005e1e4504000000000865656551acacac6a00000000", "ab53", 0, -1514251329, "136beb95459fe6b126cd6cefd54eb5d971524b0e883e41a292a78f78015cb8d5"],
+	["f10a0356031cd569d652dbca8e7a4d36c8da33cdff428d003338602b7764fe2c96c505175b010000000465ac516affffffffbb54563c71136fa944ee20452d78dc87073ac2365ba07e638dce29a5d179da600000000003635152ffffffff9a411d8e2d421b1e6085540ee2809901e590940bbb41532fa38bd7a16b68cc350100000007535251635365636195df1603b61c45010000000002ab65bf6a310400000000026352fcbba10200000000016aa30b7ff0", "5351", 0, 1552495929, "9eb8adf2caecb4bf9ac59d7f46bd20e83258472db2f569ee91aba4cf5ee78e29"],
+	["c3325c9b012f659466626ca8f3c61dfd36f34670abc054476b7516a1839ec43cd0870aa0c0000000000753525265005351e7e3f04b0112650500000000000363ac6300000000", "acac", 0, -68961433, "5ca70e727d91b1a42b78488af2ed551642c32d3de4712a51679f60f1456a8647"],
+	["2333e54c044370a8af16b9750ac949b151522ea6029bacc9a34261599549581c7b4e5ece470000000007510052006563abffffffff80630fc0155c750ce20d0ca4a3d0c8e8d83b014a5b40f0b0be0dd4c63ac28126020000000465000000ffffffff1b5f1433d38cdc494093bb1d62d84b10abbdae57e3d04e82e600857ab3b1dc990300000003515100b76564be13e4890a908ea7508afdad92ec1b200a9a67939fadce6eb7a29eb4550a0a28cb0300000001acffffffff02926c930300000000016373800201000000000153d27ee740", "ab6365ab516a53", 3, 598653797, "2be27a686eb7940dd32c44ff3a97c1b28feb7ab9c5c0b1593b2d762361cfc2db"],
+	["b500ca48011ec57c2e5252e5da6432089130603245ffbafb0e4c5ffe6090feb629207eeb0e010000000652ab6a636aab8302c9d2042b44f40500000000015278c05a050000000004ac5251524be080020000000007636aac63ac5252c93a9a04000000000965ab6553636aab5352d91f9ddb", "52005100", 0, -2024394677, "49c8a6940a461cc7225637f1e512cdd174c99f96ec05935a59637ededc77124c"],
+	["f52ff64b02ee91adb01f3936cc42e41e1672778962b68cf013293d649536b519bc3271dd2c00000000020065afee11313784849a7c15f44a61cd5fd51ccfcdae707e5896d131b082dc9322a19e12858501000000036aac654e8ca882022deb7c020000000006006a515352abd3defc0000000000016300000000", "63520063", 0, 1130989496, "7f208df9a5507e98c62cebc5c1e2445eb632e95527594929b9577b53363e96f6"],
+	["ab7d6f36027a7adc36a5cf7528fe4fb5d94b2c96803a4b38a83a675d7806dda62b380df86a0000000003000000ffffffff5bc00131e29e22057c04be854794b4877dda42e416a7a24706b802ff9da521b20000000007ac6a0065ac52ac957cf45501b9f06501000000000500ac6363ab25f1110b", "00526500536a635253", 0, 911316637, "5fa09d43c8aef6f6fa01c383a69a5a61a609cd06e37dce35a39dc9eae3ddfe6c"],
+	["f940888f023dce6360263c850372eb145b864228fdbbb4c1186174fa83aab890ff38f8c9a90300000000ffffffff01e80ccdb081e7bbae1c776531adcbfb77f2e5a7d0e5d0d0e2e6c8758470e85f00000000020053ffffffff03b49088050000000004656a52ab428bd604000000000951630065ab63ac636a0cbacf0400000000070063ac5265ac53d6e16604", "ac63", 0, 39900215, "713ddeeefcfe04929e7b6593c792a4efbae88d2b5280d1f0835d2214eddcbad6"],
+	["530ecd0b01ec302d97ef6f1b5a6420b9a239714013e20d39aa3789d191ef623fc215aa8b940200000005ac5351ab6a3823ab8202572eaa04000000000752ab6a51526563fd8a270100000000036a006581a798f0", "525153656a0063", 0, 1784562684, "fe42f73a8742676e640698222b1bd6b9c338ff1ccd766d3d88d7d3c6c6ac987e"],
+	["5d781d9303acfcce964f50865ddfddab527ea971aee91234c88e184979985c00b4de15204b0100000003ab6352a009c8ab01f93c8ef2447386c434b4498538f061845862c3f9d5751ad0fce52af442b3a902000000045165ababb909c66b5a3e7c81b3c45396b944be13b8aacfc0204f3f3c105a66fa8fa6402f1b5efddb01000000096a65ac636aacab656ac3c677c402b79fa4050000000004006aab5133e35802000000000751ab635163ab0078c2e025", "6aac51636a6a005265", 0, -882306874, "551ce975d58647f10adefb3e529d9bf9cda34751627ec45e690f135ef0034b95"],
+	["25ee54ef0187387564bb86e0af96baec54289ca8d15e81a507a2ed6668dc92683111dfb7a50100000004005263634cecf17d0429aa4d000000000007636a6aabab5263daa75601000000000251ab4df70a01000000000151980a890400000000065253ac6a006377fd24e3", "65ab", 0, 797877378, "069f38fd5d47abff46f04ee3ae27db03275e9aa4737fa0d2f5394779f9654845"],
+	["a9c57b1a018551bcbc781b256642532bbc09967f1cbe30a227d352a19365d219d3f11649a3030000000451655352b140942203182894030000000006ab00ac6aab654add350400000000003d379505000000000553abacac00e1739d36", "5363", 0, -1069721025, "6da32416deb45a0d720a1dbe6d357886eabc44029dd5db74d50feaffbe763245"],
+	["05c4fb94040f5119dc0b10aa9df054871ed23c98c890f1e931a98ffb0683dac45e98619fdc0200000007acab6a525263513e7495651c9794c4d60da835d303eb4ee6e871f8292f6ad0b32e85ef08c9dc7aa4e03c9c010000000500ab52acacfffffffffee953259cf14ced323fe8d567e4c57ba331021a1ef5ac2fa90f7789340d7c550100000007ac6aacac6a6a53ffffffff08d9dc820d00f18998af247319f9de5c0bbd52a475ea587f16101af3afab7c210100000003535363569bca7c0468e34f00000000000863536353ac51ac6584e319010000000006650052ab6a533debea030000000003ac0053ee7070020000000006ac52005253ac00000000", "6351005253", 2, 1386916157, "76c4013c40bfa1481badd9d342b6d4b8118de5ab497995fafbf73144469e5ff0"],
+	["c95ab19104b63986d7303f4363ca8f5d2fa87c21e3c5d462b99f1ebcb7c402fc012f5034780000000009006aac63ac65655265ffffffffbe91afa68af40a8700fd579c86d4b706c24e47f7379dad6133de389f815ef7f501000000046aac00abffffffff1520db0d81be4c631878494668d258369f30b8f2b7a71e257764e9a27f24b48701000000076a515100535300b0a989e1164db9499845bac01d07a3a7d6d2c2a76e4c04abe68f808b6e2ef5068ce6540e0100000009ac53636a63ab65656affffffff0309aac6050000000005ab6563656a6067e8020000000003ac536aec91c8030000000009655251ab65ac6a53acc7a45bc5", "63526a65abac", 1, 512079270, "fb7eca81d816354b6aedec8cafc721d5b107336657acafd0d246049556f9e04b"],
+	["ca66ae10049533c2b39f1449791bd6d3f039efe0a121ab7339d39ef05d6dcb200ec3fb2b3b020000000465006a53ffffffff534b8f97f15cc7fb4f4cea9bf798472dc93135cd5b809e4ca7fe4617a61895980100000000ddd83c1dc96f640929dd5e6f1151dab1aa669128591f153310d3993e562cc7725b6ae3d903000000046a52536582f8ccddb8086d8550f09128029e1782c3f2624419abdeaf74ecb24889cc45ac1a64492a0100000002516a4867b41502ee6ccf03000000000752acacab52ab6a4b7ba80000000000075151ab0052536300000000", "6553", 2, -62969257, "8085e904164ab9a8c20f58f0d387f6adb3df85532e11662c03b53c3df8c943cb"],
+	["ba646d0b0453999f0c70cb0430d4cab0e2120457bb9128ed002b6e9500e9c7f8d7baa20abe0200000001652a4e42935b21db02b56bf6f08ef4be5adb13c38bc6a0c3187ed7f6197607ba6a2c47bc8a03000000040052516affffffffa55c3cbfc19b1667594ac8681ba5d159514b623d08ed4697f56ce8fcd9ca5b0b00000000096a6a5263ac655263ab66728c2720fdeabdfdf8d9fb2bfe88b295d3b87590e26a1e456bad5991964165f888c03a0200000006630051ac00acffffffff0176fafe0100000000070063acac65515200000000", "63", 1, 2002322280, "9db4e320208185ee70edb4764ee195deca00ba46412d5527d9700c1cf1c3d057"],
+	["2ddb8f84039f983b45f64a7a79b74ff939e3b598b38f436def7edd57282d0803c7ef34968d02000000026a537eb00c4187de96e6e397c05f11915270bcc383959877868ba93bac417d9f6ed9f627a7930300000004516551abffffffffacc12f1bb67be3ae9f1d43e55fda8b885340a0df1175392a8bbd9f959ad3605003000000025163ffffffff02ff0f4700000000000070bd99040000000003ac53abf8440b42", "", 2, -393923011, "0133f1a161363b71dfb3a90065c7128c56bd0028b558b610142df79e055ab5c7"],
+	["b21fc15403b4bdaa994204444b59323a7b8714dd471bd7f975a4e4b7b48787e720cbd1f5f00000000000ffffffff311533001cb85c98c1d58de0a5fbf27684a69af850d52e22197b0dc941bc6ca9030000000765ab6363ab5351a8ae2c2c7141ece9a4ff75c43b7ea9d94ec79b7e28f63e015ac584d984a526a73fe1e04e0100000007526352536a5365ffffffff02a0a9ea030000000002ab52cfc4f300000000000465525253e8e0f342", "000000", 1, 1305253970, "d1df1f4bba2484cff8a816012bb6ec91c693e8ca69fe85255e0031711081c46a"],
+	["d1704d6601acf710b19fa753e307cfcee2735eada0d982b5df768573df690f460281aad12d0000000007656300005100acffffffff0232205505000000000351ab632ca1bc0300000000016300000000", "ac65ab65ab51", 0, 165179664, "40b4f03c68288bdc996011b0f0ddb4b48dc3be6762db7388bdc826113266cd6c"],
+	["d2f6c096025cc909952c2400bd83ac3d532bfa8a1f8f3e73c69b1fd7b8913379793f3ce92202000000076a00ab6a53516ade5332d81d58b22ed47b2a249ab3a2cb3a6ce9a6b5a6810e18e3e1283c1a1b3bd73e3ab00300000002acabffffffff01a9b2d40500000000056352abab00dc4b7f69", "ab0065", 0, -78019184, "2ef025e907f0fa454a2b48a4f3b81346ba2b252769b5c35d742d0c8985e0bf5e"],
+	["3e6db1a1019444dba461247224ad5933c997256d15c5d37ade3d700506a0ba0a57824930d7010000000852ab6500ab00ac00ffffffff03389242020000000001aba8465a0200000000086a6a636a5100ab52394e6003000000000953ac51526351000053d21d9800", "abababacab53ab65", 0, 1643661850, "1f8a3aca573a609f4aea0c69522a82fcb4e15835449da24a05886ddc601f4f6a"],
+	["f821a042036ad43634d29913b77c0fc87b4af593ac86e9a816a9d83fd18dfcfc84e1e1d57102000000076a63ac52006351ffffffffbcdaf490fc75086109e2f832c8985716b3a624a422cf9412fe6227c10585d21203000000095252abab5352ac526affffffff2efed01a4b73ad46c7f7bc7fa3bc480f8e32d741252f389eaca889a2e9d2007e000000000353ac53ffffffff032ac8b3020000000009636300000063516300d3d9f2040000000006510065ac656aafa5de0000000000066352ab5300ac9042b57d", "525365", 1, 667065611, "0d17a92c8d5041ba09b506ddf9fd48993be389d000aad54f9cc2a44fcc70426b"],
+	["58e3f0f704a186ef55d3919061459910df5406a9121f375e7502f3be872a449c3f2bb058380100000000f0e858da3ac57b6c973f889ad879ffb2bd645e91b774006dfa366c74e2794aafc8bbc871010000000751ac65516a515131a68f120fd88ca08687ceb4800e1e3fbfea7533d34c84fef70cc5a96b648d580369526d000000000600ac00515363f6191d5b3e460fa541a30a6e83345dedfa3ed31ad8574d46d7bbecd3c9074e6ba5287c24020000000151e3e19d6604162602010000000004005100ac71e17101000000000065b5e90300000000040053ab53f6b7d101000000000200ac00000000", "6563ab", 1, -669018604, "8221d5dfb75fc301a80e919e158e0b1d1e86ffb08870a326c89408d9bc17346b"],
+	["efec1cce044a676c1a3d973f810edb5a9706eb4cf888a240f2b5fb08636bd2db482327cf500000000005ab51656a52ffffffff46ef019d7c03d9456e5134eb0a7b5408d274bd8e33e83df44fab94101f7c5b650200000009ac5100006353630051407aadf6f5aaffbd318fdbbc9cae4bd883e67d524df06bb006ce2f7c7e2725744afb76960100000005536aab53acec0d64eae09e2fa1a7c4960354230d51146cf6dc45ee8a51f489e20508a785cbe6ca86fc000000000651536a516300ffffffff014ef598020000000006636aac655265a6ae1b75", "53516a5363526563ab", 2, -1823982010, "13e8b5ab4e5b2ceeff0045c625e19898bda2d39fd7af682e2d1521303cfe1154"],
+	["3c436c2501442a5b700cbc0622ee5143b34b1b8021ea7bbc29e4154ab1f5bdfb3dff9d640501000000086aab5251ac5252acffffffff0170b9a20300000000066aab6351525114b13791", "63acabab52ab51ac65", 0, -2140612788, "87ddf1f9acb6640448e955bd1968f738b4b3e073983af7b83394ab7557f5cd61"],
+	["d62f183e037e0d52dcf73f9b31f70554bce4f693d36d17552d0e217041e01f15ad3840c838000000000963acac6a6a6a63ab63ffffffffabdfb395b6b4e63e02a763830f536fc09a35ff8a0cf604021c3c751fe4c88f4d0300000006ab63ab65ac53aa4d30de95a2327bccf9039fb1ad976f84e0b4a0936d82e67eafebc108993f1e57d8ae39000000000165ffffffff04364ad30500000000036a005179fd84010000000007ab636aac6363519b9023030000000008510065006563ac6acd2a4a02000000000000000000", "52", 1, 595020383, "da8405db28726dc4e0f82b61b2bfd82b1baa436b4e59300305cc3b090b157504"],
+	["44c200a5021238de8de7d80e7cce905606001524e21c8d8627e279335554ca886454d692e6000000000500acac52abbb8d1dc876abb1f514e96b21c6e83f429c66accd961860dc3aed5071e153e556e6cf076d02000000056553526a51870a928d0360a580040000000004516a535290e1e302000000000851ab6a00510065acdd7fc5040000000007515363ab65636abb1ec182", "6363", 0, -785766894, "ed53cc766cf7cb8071cec9752460763b504b2183442328c5a9761eb005c69501"],
+	["d682d52d034e9b062544e5f8c60f860c18f029df8b47716cabb6c1b4a4b310a0705e754556020000000400656a0016eeb88eef6924fed207fba7ddd321ff3d84f09902ff958c815a2bf2bb692eb52032c4d803000000076365ac516a520099788831f8c8eb2552389839cfb81a9dc55ecd25367acad4e03cfbb06530f8cccf82802701000000085253655300656a53ffffffff02d543200500000000056a510052ac03978b05000000000700ac51525363acfdc4f784", "", 2, -696035135, "e1a256854099907050cfee7778f2018082e735a1f1a3d91437584850a74c87bb"],
+	["e8c0dec5026575ddf31343c20aeeca8770afb33d4e562aa8ee52eeda6b88806fdfd4fe0a97030000000953acabab65ab516552ffffffffdde122c2c3e9708874286465f8105f43019e837746686f442666629088a970e0010000000153ffffffff01f98eee0100000000025251fe87379a", "63", 1, 633826334, "abe441209165d25bc6d8368f2e7e7dc21019056719fef1ace45542aa2ef282e2"],
+	["b288c331011c17569293c1e6448e33a64205fc9dc6e35bc756a1ac8b97d18e912ea88dc0770200000007635300ac6aacabfc3c890903a3ccf8040000000004656500ac9c65c9040000000009ab6a6aabab65abac63ac5f7702000000000365005200000000", "526a63", 0, 1574937329, "0dd1bd5c25533bf5f268aa316ce40f97452cca2061f0b126a59094ca5b65f7a0"],
+	["fc0a092003cb275fa9a25a72cf85d69c19e4590bfde36c2b91cd2c9c56385f51cc545530210000000004ab530063ffffffff729b006eb6d14d6e5e32b1c376acf1c62830a5d9246da38dbdb4db9f51fd1c74020000000463636500ffffffff0ae695c6d12ab7dcb8d3d4b547b03f178c7268765d1de9af8523d244e3836b12030000000151ffffffff0115c1e20100000000066a6aabac6a6a1ff59aec", "ab0053ac", 0, 931831026, "73fe22099c826c34a74edf45591f5d7b3a888c8178cd08facdfd96a9a681261c"],
+	["0fcae7e004a71a4a7c8f66e9450c0c1785268679f5f1a2ee0fb3e72413d70a9049ecff75de020000000452005251ffffffff99c8363c4b95e7ec13b8c017d7bb6e80f7c04b1187d6072961e1c2479b1dc0320200000000ffffffff7cf03b3d66ab53ed740a70c5c392b84f780fff5472aee82971ac3bfeeb09b2df0200000006ab5265636a0058e4fe9257d7c7c7e82ff187757c6eadc14cceb6664dba2de03a018095fd3006682a5b9600000000056353536a636de26b2303ff76de010000000001acdc0a2e020000000001ab0a53ed020000000007530063ab51510088417307", "ac6aacab5165535253", 2, -902160694, "eea96a48ee572aea33d75d0587ce954fcfb425531a7da39df26ef9a6635201be"],
+	["612701500414271138e30a46b7a5d95c70c78cc45bf8e40491dac23a6a1b65a51af04e6b94020000000451655153ffffffffeb72dc0e49b2fad3075c19e1e6e4b387f1365dca43d510f6a02136318ddecb7f0200000003536352e115ffc4f9bae25ef5baf534a890d18106fb07055c4d7ec9553ba89ed1ac2101724e507303000000080063006563acabac2ff07f69a080cf61a9d19f868239e6a4817c0eeb6a4f33fe254045d8af2bca289a8695de0300000000430736c404d317840500000000086a00abac5351ab65306e0503000000000963ab0051536aabab6a6c8aca01000000000565516351ab5dcf960100000000016a00000000", "ab", 2, -604581431, "5ec805e74ee934aa815ca5f763425785ae390282d46b5f6ea076b6ad6255a842"],
+	["6b68ba00023bb4f446365ea04d68d48539aae66f5b04e31e6b38b594d2723ab82d44512460000000000200acffffffff5dfc6febb484fff69c9eeb7c7eb972e91b6d949295571b8235b1da8955f3137b020000000851ac6352516a535325828c8a03365da801000000000800636aabac6551ab0f594d03000000000963ac536365ac63636a45329e010000000005abac53526a00000000", "005151", 0, 1317038910, "42f5ba6f5fe1e00e652a08c46715871dc4b40d89d9799fd7c0ea758f86eab6a7"],
+	["aff5850c0168a67296cc790c1b04a9ed9ad1ba0469263a9432fcb53676d1bb4e0eea8ea1410100000005ac65526a537d5fcb1d01d9c26d0200000000065265ab5153acc0617ca1", "51ab650063", 0, 1712981774, "8449d5247071325e5f8edcc93cb9666c0fecabb130ce0e5bef050575488477eb"],
+	["e6d6b9d8042c27aec99af8c12b6c1f7a80453e2252c02515e1f391da185df0874e133696b50300000006ac5165650065ffffffff6a4b60a5bfe7af72b198eaa3cde2e02aa5fa36bdf5f24ebce79f6ecb51f3b554000000000652656aababac2ec4c5a6cebf86866b1fcc4c5bd5f4b19785a8eea2cdfe58851febf87feacf6f355324a80100000001537100145149ac1e287cef62f6f5343579189fad849dd33f25c25bfca841cb696f10c5a34503000000046a636a63df9d7c4c018d96e20100000000015100000000", "53ab", 1, -1924777542, "f98f95d0c5ec3ac3e699d81f6c440d2e7843eab15393eb023bc5a62835d6dcea"],
+	["046ac25e030a344116489cc48025659a363da60bc36b3a8784df137a93b9afeab91a04c1ed020000000951ab0000526a65ac51ffffffff6c094a03869fde55b9a8c4942a9906683f0a96e2d3e5a03c73614ea3223b2c29020000000500ab636a6affffffff3da7aa5ecef9071600866267674b54af1740c5aeb88a290c459caa257a2683cb0000000004ab6565ab7e2a1b900301b916030000000005abac63656308f4ed03000000000852ab53ac63ac51ac73d620020000000003ab00008deb1285", "6a", 2, 1299505108, "f79e6b776e2592bad45ca328c54abf14050c241d8f822d982c36ea890fd45757"],
+	["bd515acd0130b0ac47c2d87f8d65953ec7d657af8d96af584fc13323d0c182a2e5f9a96573000000000652ac51acac65ffffffff0467aade000000000003655363dc577d050000000006515252ab5300137f60030000000007535163530065004cdc860500000000036a5265241bf53e", "acab", 0, 621090621, "771d4d87f1591a13d77e51858c16d78f1956712fe09a46ff1abcabbc1e7af711"],
+	["ff1ae37103397245ac0fa1c115b079fa20930757f5b6623db3579cb7663313c2dc4a3ffdb300000000076353656a000053ffffffff83c59e38e5ad91216ee1a312d15b4267bae2dd2e57d1a3fd5c2f0f809eeb5d46010000000800abab6a6a53ab51ffffffff9d5e706c032c1e0ca75915f8c6686f64ec995ebcd2539508b7dd8abc3e4d7d2a01000000006b2bdcda02a8fe070500000000045253000019e31d04000000000700ab63acab526a00000000", "53656aab6a525251", 0, 881938872, "726bb88cdf3af2f7603a31f33d2612562306d08972a4412a55dbbc0e3363721c"],
+	["ff5400dd02fec5beb9a396e1cbedc82bedae09ed44bae60ba9bef2ff375a6858212478844b03000000025253ffffffff01e46c203577a79d1172db715e9cc6316b9cfc59b5e5e4d9199fef201c6f9f0f000000000900ab6552656a5165acffffffff02e8ce62040000000002515312ce3e00000000000251513f119316", "", 0, 1541581667, "1e0da47eedbbb381b0e0debbb76e128d042e02e65b11125e17fd127305fc65cd"],
+	["28e3daa603c03626ad91ffd0ff927a126e28d29db5012588b829a06a652ea4a8a5732407030200000004ab6552acffffffff8e643146d3d0568fc2ad854fd7864d43f6f16b84e395db82b739f6f5c84d97b40000000004515165526b01c2dc1469db0198bd884e95d8f29056c48d7e74ff9fd37a9dec53e44b8769a6c99c030200000009ab006a516a53630065eea8738901002398000000000007ac5363516a51abeaef12f5", "52ab52515253ab", 2, 1687390463, "55591346aec652980885a558cc5fc2e3f8d21cbd09f314a798e5a7ead5113ea6"],
+	["b54bf5ac043b62e97817abb892892269231b9b220ba08bc8dbc570937cd1ea7cdc13d9676c010000000451ab5365a10adb7b35189e1e8c00b86250f769319668189b7993d6bdac012800f1749150415b2deb0200000003655300ffffffff60b9f4fb9a7e17069fd00416d421f804e2ef2f2c67de4ca04e0241b9f9c1cc5d0200000003ab6aacfffffffff048168461cce1d40601b42fbc5c4f904ace0d35654b7cc1937ccf53fe78505a0100000008526563525265abacffffffff01dbf4e6040000000007acac656553636500000000", "63", 2, 882302077, "f5b38b0f06e246e47ce622e5ee27d5512c509f8ac0e39651b3389815eff2ab93"],
+	["ebf628b30360bab3fa4f47ce9e0dcbe9ceaf6675350e638baff0c2c197b2419f8e4fb17e16000000000452516365ac4d909a79be207c6e5fb44fbe348acc42fc7fe7ef1d0baa0e4771a3c4a6efdd7e2c118b0100000003acacacffffffffa6166e9101f03975721a3067f1636cc390d72617be72e5c3c4f73057004ee0ee010000000863636a6a516a5252c1b1e82102d8d54500000000000153324c900400000000015308384913", "0063516a51", 1, -1658428367, "eb2d8dea38e9175d4d33df41f4087c6fea038a71572e3bad1ea166353bf22184"],
+	["d6a8500303f1507b1221a91adb6462fb62d741b3052e5e7684ea7cd061a5fc0b0e93549fa50100000004acab65acfffffffffdec79bf7e139c428c7cfd4b35435ae94336367c7b5e1f8e9826fcb0ebaaaea30300000000ffffffffd115fdc00713d52c35ea92805414bd57d1e59d0e6d3b79a77ee18a3228278ada020000000453005151ffffffff040231510300000000085100ac6a6a000063c6041c0400000000080000536a6563acac138a0b04000000000263abd25fbe03000000000900656a00656aac510000000000", "ac526aac6a00", 1, -2007972591, "13d12a51598b34851e7066cd93ab8c5212d60c6ed2dae09d91672c10ccd7f87c"],
+	["658cb1c1049564e728291a56fa79987a4ed3146775fce078bd2e875d1a5ca83baf6166a82302000000056a656351ab2170e7d0826cbdb45fda0457ca7689745fd70541e2137bb4f52e7b432dcfe2112807bd720300000007006a0052536351ffffffff8715ca2977696abf86d433d5c920ef26974f50e9f4a20c584fecbb68e530af5101000000009e49d864155bf1d3c757186d29f3388fd89c7f55cc4d9158b4cf74ca27a35a1dd93f945502000000096a535353ac656351510d29fa870230b809040000000006ab6a6a526a633b41da050000000004ab6a6a65ed63bf62", "52acabac", 2, -1774073281, "53ab197fa7e27b8a3f99ff48305e67081eb90e95d89d7e92d80cee25a03a6689"],
+	["e92492cc01aec4e62df67ea3bc645e2e3f603645b3c5b353e4ae967b562d23d6e043badecd0100000003acab65ffffffff02c7e5ea040000000002ab52e1e584010000000005536365515195d16047", "6551", 0, -424930556, "93c34627f526d73f4bea044392d1a99776b4409f7d3d835f23b03c358f5a61c2"],
+	["02e242db04be2d8ced9179957e98cee395d4767966f71448dd084426844cbc6d15f2182e85030000000200650c8ffce3db9de9c3f9cdb9104c7cb26647a7531ad1ebf7591c259a9c9985503be50f8de30000000007ac6a51636a6353ffffffffa2e33e7ff06fd6469987ddf8a626853dbf30c01719efb259ae768f051f803cd30300000000fffffffffd69d8aead941683ca0b1ee235d09eade960e0b1df3cd99f850afc0af1b73e070300000001ab60bb602a011659670100000000076363526300acac00000000", "6353ab515251", 3, 1451100552, "bbc9069b8615f3a52ac8a77359098dcc6c1ba88c8372d5d5fe080b99eb781e55"],
+	["b28d5f5e015a7f24d5f9e7b04a83cd07277d452e898f78b50aae45393dfb87f94a26ef57720200000008ababac630053ac52ffffffff046475ed040000000008ab5100526363ac65c9834a04000000000251abae26b30100000000040000ac65ceefb900000000000000000000", "ac6551ac6a536553", 0, -1756558188, "5848d93491044d7f21884eef7a244fe7d38886f8ae60df49ce0dfb2a342cd51a"],
+	["efb8b09801f647553b91922a5874f8e4bb2ed8ddb3536ed2d2ed0698fac5e0e3a298012391030000000952ac005263ac52006affffffff04cdfa0f050000000007ac53ab51abac65b68d1b02000000000553ab65ac00d057d50000000000016a9e1fda010000000007ac63ac536552ac00000000", "6aac", 0, 1947322973, "603a9b61cd30fcea43ef0a5c18b88ca372690b971b379ee9e01909c336280511"],
+	["68a59fb901c21946797e7d07a4a3ea86978ce43df0479860d7116ac514ba955460bae78fff0000000001abffffffff03979be80100000000036553639300bc040000000008006552006a656565cfa78d0000000000076552acab63ab5100000000", "ab65ab", 0, 995583673, "3b320dd47f2702452a49a1288bdc74a19a4b849b132b6cad9a1d945d87dfbb23"],
+	["67761f2a014a16f3940dcb14a22ba5dc057fcffdcd2cf6150b01d516be00ef55ef7eb07a830100000004636a6a51ffffffff01af67bd050000000008526553526300510000000000", "6a00", 0, 1570943676, "079fa62e9d9d7654da8b74b065da3154f3e63c315f25751b4d896733a1d67807"],
+	["e20fe96302496eb436eee98cd5a32e1c49f2a379ceb71ada8a48c5382df7c8cd88bdc47ced03000000016556aa0e180660925a841b457aed0aae47fca2a92fa1d7afeda647abf67198a3902a7c80dd00000000085152ac636a535265bd18335e01803c810100000000046500ac52f371025e", "6363ab", 1, -651254218, "2921a0e5e3ba83c57ba57c25569380c17986bf34c366ec216d4188d5ba8b0b47"],
+	["4e1bd9fa011fe7aa14eee8e78f27c9fde5127f99f53d86bc67bdab23ca8901054ee8a8b6eb0300000009ac535153006a6a0063ffffffff044233670500000000000a667205000000000652ab636a51abe5bf35030000000003535351d579e505000000000700630065ab51ac3419ac30", "52abac52", 0, -1807563680, "4aae6648f856994bed252d319932d78db55da50d32b9008216d5366b44bfdf8a"],
+	["ec02fbee03120d02fde12574649660c441b40d330439183430c6feb404064d4f507e704f3c0100000000ffffffffe108d99c7a4e5f75cc35c05debb615d52fac6e3240a6964a29c1704d98017fb60200000002ab63fffffffff726ec890038977adfc9dadbeaf5e486d5fcb65dc23acff0dd90b61b8e2773410000000002ac65e9dace55010f881b010000000005ac00ab650000000000", "51ac525152ac6552", 2, -1564046020, "3f988922d8cd11c7adff1a83ce9499019e5ab5f424752d8d361cf1762e04269b"],
+	["23dbdcc1039c99bf11938d8e3ccec53b60c6c1d10c8eb6c31197d62c6c4e2af17f52115c3a0300000008636352000063ababffffffff17823880e1df93e63ad98c29bfac12e36efd60254346cac9d3f8ada020afc0620300000003ab63631c26f002ac66e86cd22a25e3ed3cb39d982f47c5118f03253054842daadc88a6c41a2e1500000000096a00ab636a53635163195314de015570fd0100000000096a5263acab5200005300000000", "ababac6a6553", 1, 11586329, "bd36a50e0e0a4ecbf2709e68daef41eddc1c0c9769efaee57910e99c0a1d1343"],
+	["33b03bf00222c7ca35c2f8870bbdef2a543b70677e413ce50494ac9b22ea673287b6aa55c50000000005ab00006a52ee4d97b527eb0b427e4514ea4a76c81e68c34900a23838d3e57d0edb5410e62eeb8c92b6000000000553ac6aacac42e59e170326245c000000000009656553536aab516aabb1a10603000000000852ab52ab6a516500cc89c802000000000763ac6a63ac516300000000", "", 0, 557416556, "41bead1b073e1e9fee065dd612a617ca0689e8f9d3fed9d0acfa97398ebb404c"],
+	["813eda1103ac8159850b4524ef65e4644e0fc30efe57a5db0c0365a30446d518d9b9aa8fdd0000000003656565c2f1e89448b374b8f12055557927d5b33339c52228f7108228149920e0b77ef0bcd69da60000000006abac00ab63ab82cdb7978d28630c5e1dc630f332c4245581f787936f0b1e84d38d33892141974c75b4750300000004ac53ab65ffffffff0137edfb02000000000000000000", "0063", 1, -1948560575, "71dfcd2eb7f2e6473aed47b16a6d5fcbd0af22813d892e9765023151e07771ec"],
+	["9e45d9aa0248c16dbd7f435e8c54ae1ad086de50c7b25795a704f3d8e45e1886386c653fbf01000000025352fb4a1acefdd27747b60d1fb79b96d14fb88770c75e0da941b7803a513e6d4c908c6445c7010000000163ffffffff014069a8010000000001520a794fb3", "51ac005363", 1, -719113284, "0d31a221c69bd322ef7193dd7359ddfefec9e0a1521d4a8740326d46e44a5d6a"],
+	["36e42018044652286b19a90e5dd4f8d9f361d0760d080c5c5add1970296ff0f1de630233c8010000000200ac39260c7606017d2246ee14ddb7611586178067e6a4be38e788e33f39a3a95a55a13a6775010000000352ac638bea784f7c2354ed02ea0b93f0240cdfb91796fa77649beee6f7027caa70778b091deee700000000066a65ac656363ffffffff4d9d77ab676d711267ef65363f2d192e1bd55d3cd37f2280a34c72e8b4c559d700000000056a006aab00001764e1020d30220100000000085252516aacab0053472097040000000009635353ab6a636a5100a56407a1", "006a536551ab53ab", 0, 827296034, "daec2af5622bbe220c762da77bab14dc75e7d28aa1ade9b7f100798f7f0fd97a"],
+	["5e06159a02762b5f3a5edcdfc91fd88c3bff08b202e69eb5ba74743e9f4291c4059ab008200000000001ac348f5446bb069ef977f89dbe925795d59fb5d98562679bafd61f5f5f3150c3559582992d0000000008ab5165515353abac762fc67703847ec6010000000000e200cf040000000002abaca64b86010000000008520000515363acabb82b491b", "ab53525352ab6a", 0, -61819505, "75a7db0df41485a28bf6a77a37ca15fa8eccc95b5d6014a731fd8adb9ada0f12"],
+	["a1948872013b543d6d902ccdeead231c585195214ccf5d39f136023855958436a43266911501000000086aac006a6a6a51514951c9b2038a538a04000000000452526563c0f345050000000007526a5252ac526af9be8e03000000000752acac51ab006306198db2", "ab6353", 0, -326384076, "ced7ef84aad4097e1eb96310e0d1c8e512cfcb392a01d9010713459b23bc0cf4"],
+	["c3efabba03cb656f154d1e159aa4a1a4bf9423a50454ebcef07bc3c42a35fb8ad84014864d0000000000d1cc73d260980775650caa272e9103dc6408bdacaddada6b9c67c88ceba6abaa9caa2f7d020000000553536a5265ffffffff9f946e8176d9b11ff854b76efcca0a4c236d29b69fb645ba29d406480427438e01000000066a0065005300ffffffff040419c0010000000003ab6a63cdb5b6010000000009006300ab5352656a63f9fe5e050000000004acac5352611b980100000000086a00acac00006a512d7f0c40", "0053", 0, -59089911, "c503001c16fbff82a99a18d88fe18720af63656fccd8511bca1c3d0d69bd7fc0"],
+	["efb55c2e04b21a0c25e0e29f6586be9ef09f2008389e5257ebf2f5251051cdc6a79fce2dac020000000351006affffffffaba73e5b6e6c62048ba5676d18c33ccbcb59866470bb7911ccafb2238cfd493802000000026563ffffffffe62d7cb8658a6eca8a8babeb0f1f4fa535b62f5fc0ec70eb0111174e72bbec5e0300000009abababac516365526affffffffbf568789e681032d3e3be761642f25e46c20322fa80346c1146cb47ac999cf1b0300000000b3dbd55902528828010000000001ab0aac7b0100000000015300000000", "acac52", 3, 1638140535, "e84444d91580da41c8a7dcf6d32229bb106f1be0c811b2292967ead5a96ce9d4"],
+	["91d3b21903629209b877b3e1aef09cd59aca6a5a0db9b83e6b3472aceec3bc2109e64ab85a0200000003530065ffffffffca5f92de2f1b7d8478b8261eaf32e5656b9eabbc58dcb2345912e9079a33c4cd010000000700ab65ab00536ad530611da41bbd51a389788c46678a265fe85737b8d317a83a8ff7a839debd18892ae5c80300000007ab6aac65ab51008b86c501038b8a9a05000000000263525b3f7a040000000007ab535353ab00abd4e3ff04000000000665ac51ab65630b7b656f", "6551525151516a00", 2, 499657927, "ef4bd7622eb7b2bbbbdc48663c1bc90e01d5bde90ff4cb946596f781eb420a0c"],
+	["5d5c41ad0317aa7e40a513f5141ad5fc6e17d3916eebee4ddb400ddab596175b41a111ead20100000005536a5265acffffffff900ecb5e355c5c9f278c2c6ea15ac1558b041738e4bffe5ae06a9346d66d5b2b00000000080000ab636a65ab6affffffff99f4e08305fa5bd8e38fb9ca18b73f7a33c61ff7b3c68e696b30a04fea87f3ca000000000163d3d1760d019fc13a00000000000000000000", "ab53acabab6aac6a52", 2, 1007461922, "4012f5ff2f1238a0eb84854074670b4703238ebc15bfcdcd47ffa8498105fcd9"],
+	["ceecfa6c02b7e3345445b82226b15b7a097563fa7d15f3b0c979232b138124b62c0be007890200000009abac51536a63525253ffffffffbae481ccb4f15d94db5ec0d8854c24c1cc8642bd0c6300ede98a91ca13a4539a0200000001ac50b0813d023110f5020000000006acabac526563e2b0d0040000000009656aac0063516a536300000000", "0063526500", 0, -1862053821, "e1600e6df8a6160a79ac32aa40bb4644daa88b5f76c0d7d13bf003327223f70c"],
+	["ae62d5fd0380c4083a26642159f51af24bf55dc69008e6b7769442b6a69a603edd980a33000000000005ab5100ab53ffffffff49d048324d899d4b8ed5e739d604f5806a1104fede4cb9f92cc825a7fa7b4bfe0200000005536a000053ffffffff42e5cea5673c650881d0b4005fa4550fd86de5f21509c4564a379a0b7252ac0e0000000007530000526a53525f26a68a03bfacc3010000000000e2496f000000000009ab5253acac52636563b11cc600000000000700510065526a6a00000000", "abab", 1, -1600104856, "05cf0ec9c61f1a15f651a0b3c5c221aa543553ce6c804593f43bb5c50bb91ffb"],
+	["f06f64af04fdcb830464b5efdb3d5ee25869b0744005375481d7b9d7136a0eb8828ad1f0240200000003516563fffffffffd3ba192dabe9c4eb634a1e3079fca4f072ee5ceb4b57deb6ade5527053a92c5000000000165ffffffff39f43401a36ba13a5c6dd7f1190e793933ae32ee3bf3e7bfb967be51e681af760300000009650000536552636a528e34f50b21183952cad945a83d4d56294b55258183e1627d6e8fb3beb8457ec36cadb0630000000005abab530052334a7128014bbfd10100000000085352ab006a63656afc424a7c", "53650051635253ac00", 2, 313255000, "d309da5afd91b7afa257cfd62df3ca9df036b6a9f4b38f5697d1daa1f587312b"],
+	["6dfd2f98046b08e7e2ef5fff153e00545faf7076699012993c7a30cb1a50ec528281a9022f030000000152ffffffff1f535e4851920b968e6c437d84d6ecf586984ebddb7d5db6ae035bd02ba222a8010000000651006a53ab51605072acb3e17939fa0737bc3ee43bc393b4acd58451fc4ffeeedc06df9fc649828822d5010000000253525a4955221715f27788d302382112cf60719be9ae159c51f394519bd5f7e70a4f9816c7020200000009526a6a51636aab656a36d3a5ff0445548e0100000000086a6a00516a52655167030b050000000004ac6a63525cfda8030000000000e158200000000000010000000000", "535263ac6a65515153", 3, 585774166, "72b7da10704c3ca7d1deb60c31b718ee12c70dc9dfb9ae3461edce50789fe2ba"],
+	["187eafed01389a45e75e9dda526d3acbbd41e6414936b3356473d1f9793d161603efdb45670100000002ab00ffffffff04371c8202000000000563630063523b3bde02000000000753516563006300e9e765010000000005516aac656a373f9805000000000665525352acab08d46763", "ab", 0, 122457992, "393aa6c758e0eed15fa4af6d9e2d7c63f49057246dbb92b4268ec24fc87301ca"],
+	["7d50b977035d50411d814d296da9f7965ddc56f3250961ca5ba805cadd0454e7c521e31b0300000000003d0416c2cf115a397bacf615339f0e54f6c35ffec95aa009284d38390bdde1595cc7aa7c0100000005ab52ac5365ffffffff4232c6e796544d5ac848c9dc8d25cfa74e32e847a5fc74c74d8f38ca51188562030000000653ac51006a51ffffffff016bd8bb00000000000465ab5253163526f3", "51ab526a00005353", 1, -1311316785, "60b7544319b42e4159976c35c32c2644f0adf42eff13be1dc2f726fc0b6bb492"],
+	["2a45cd1001bf642a2315d4a427eddcc1e2b0209b1c6abd2db81a800c5f1af32812de42032702000000050051525200ffffffff032177db050000000005530051abac49186f000000000004ab6aab00645c0000000000000765655263acabac00000000", "6a65", 0, -1774715722, "6a9ac3f7da4c7735fbc91f728b52ecbd602233208f96ac5592656074a5db118a"],
+	["479358c202427f3c8d19e2ea3def6d6d3ef2281b4a93cd76214f0c7d8f040aa042fe19f71f0300000001abffffffffa2709be556cf6ecaa5ef530df9e4d056d0ed57ce96de55a5b1f369fa40d4e74a020000000700006a51635365c426be3f02af578505000000000363ab63fd8f590500000000065153abac53632dfb14b3", "520063ab51", 1, -763226778, "cfe147982afacde044ce66008cbc5b1e9f0fd9b8ed52b59fc7c0fecf95a39b0e"],
+	["76179a8e03bec40747ad65ab0f8a21bc0d125b5c3c17ad5565556d5cb03ade7c83b4f32d98030000000151ffffffff99b900504e0c02b97a65e24f3ad8435dfa54e3c368f4e654803b756d011d24150200000003ac5353617a04ac61bb6cf697cfa4726657ba35ed0031432da8c0ffb252a190278830f9bd54f0320100000006656551005153c8e8fc8803677c77020000000007ac6553535253ac70f442030000000001535be0f20200000000026300bf46cb3a", "6aab52", 1, -58495673, "35e94b3776a6729d20aa2f3ddeeb06d3aad1c14cc4cde52fd21a4efc212ea16c"],
+	["75ae53c2042f7546223ce5d5f9e00a968ddc68d52e8932ef2013fa40ce4e8c6ed0b6195cde01000000056563ac630079da0452c20697382e3dba6f4fc300da5f52e95a9dca379bb792907db872ba751b8024ee0300000009655151536500005163ffffffffe091b6d43f51ff00eff0ccfbc99b72d3aff208e0f44b44dfa5e1c7322cfc0c5f01000000075200005363ab63ffffffff7e96c3b83443260ac5cfd18258574fbc4225c630d3950df812bf51dceaeb0f9103000000065365655165639a6bf70b01b3e14305000000000563530063ac00000000", "6300ab00ac", 2, 982422189, "ee4ea49d2aae0dbba05f0b9785172da54408eb1ec67d36759ff7ed25bfc28766"],
+	["1cdfa01e01e1b8078e9c2b0ca5082249bd18fdb8b629ead659adedf9a0dd5a04031871ba120200000008525351536565ab6affffffff011e28430200000000076a5363636aac52b2febd4a", "abacac63656300", 0, 387396350, "299dcaac2bdaa627eba0dfd74767ee6c6f27c9200b49da8ff6270b1041669e7e"],
+	["cc28c1810113dfa6f0fcd9c7d9c9a30fb6f1d774356abeb527a8651f24f4e6b25cf763c4e00300000003ab636affffffff02dfc6050000000000080053636351ab0052afd56903000000000453ab5265f6c90d99", "006551abacacac", 0, 1299280838, "a4c0773204ab418a939e23f493bd4b3e817375d133d307609e9782f2cc38dbcf"],
+	["ca816e7802cd43d66b9374cd9bf99a8da09402d69c688d8dcc5283ace8f147e1672b757e020200000005516aabab5240fb06c95c922342279fcd88ba6cd915933e320d7becac03192e0941e0345b79223e89570300000004005151ac353ecb5d0264dfbd010000000005ac6aacababd5d70001000000000752ac53ac6a5151ec257f71", "63ac", 1, 774695685, "cc180c4f797c16a639962e7aec58ec4b209853d842010e4d090895b22e7a7863"],
+	["b42b955303942fedd7dc77bbd9040aa0de858afa100f399d63c7f167b7986d6c2377f66a7403000000066aac00525100ffffffff0577d04b64880425a3174055f94191031ad6b4ca6f34f6da9be7c3411d8b51fc000000000300526a6391e1cf0f22e45ef1c44298523b516b3e1249df153590f592fcb5c5fc432dc66f3b57cb03000000046a6aac65ffffffff0393a6c9000000000004516a65aca674ac0400000000046a525352c82c370000000000030053538e577f89", "", 1, -1237094944, "566953eb806d40a9fb684d46c1bf8c69dea86273424d562bd407b9461c8509af"],
+	["92c9fe210201e781b72554a0ed5e22507fb02434ddbaa69aff6e74ea8bad656071f1923f3f02000000056a63ac6a514470cef985ba83dcb8eee2044807bedbf0d983ae21286421506ae276142359c8c6a34d68020000000863ac63525265006aa796dd0102ca3f9d05000000000800abab52ab535353cd5c83010000000007ac00525252005322ac75ee", "5165", 0, 97879971, "6e6307cef4f3a9b386f751a6f40acebab12a0e7e17171d2989293cbec7fd45c2"],
+	["ccca1d5b01e40fe2c6b3ee24c660252134601dab785b8f55bd6201ffaf2fddc7b3e2192325030000000365535100496d4703b4b66603000000000665535253ac633013240000000000015212d2a502000000000951abac636353636a5337b82426", "0052", 0, -1691630172, "577bf2b3520b40aef44899a20d37833f1cded6b167e4d648fc5abe203e43b649"],
+	["bc1a7a3c01691e2d0c4266136f12e391422f93655c71831d90935fbda7e840e50770c61da20000000008635253abac516353ffffffff031f32aa020000000003636563786dbc0200000000003e950f00000000000563516a655184b8a1de", "51536a", 0, -1627072905, "730bc25699b46703d7718fd5f5c34c4b5f00f594a9968ddc247fa7d5175124ed"],
+	["076d209e02d904a6c40713c7225d23e7c25d4133c3c3477828f98c7d6dbd68744023dbb66b030000000753ab00536565acffffffff10975f1b8db8861ca94c8cc7c7cff086ddcd83e10b5fffd4fc8f2bdb03f9463c0100000000ffffffff029dff76010000000006526365530051a3be6004000000000000000000", "515253ac65acacac", 1, -1207502445, "66c488603b2bc53f0d22994a1f0f66fb2958203102eba30fe1d37b27a55de7a5"],
+	["690fd1f80476db1f9eebe91317f2f130a60cbc1f4feadd9d6474d438e9cb7f91e4994600af0300000004ab536a63a15ce9fa6622d0c4171d895b42bff884dc6e8a7452f827fdc68a29c3c88e6fdee364eaf50000000002ab52ffffffff022dc39d3c0956b24d7f410b1e387859e7a72955f45d6ffb1e884d77888d18fe0300000005ac6a63656afffffffff10b06bce1800f5c49153d24748fdefb0bf514c12863247d1042d56018c3e25c03000000086a63ac6365536a52ffffffff031f162f0500000000060000655265abffbcd40500000000045151ac001a9c8c05000000000652ac53656a6300000000", "ac51ab63acac", 0, -67986012, "051c0df7ac688c2c930808dabde1f50300aea115f2bb3334f4753d5169b51e46"],
+	["49ac2af00216c0307a29e83aa5de19770e6b20845de329290bd69cf0e0db7aed61ae41b39002000000035163ac8b2558ef84635bfc59635150e90b61fc753d34acfd10d97531043053e229cd720133cd95000000000463516a51ffffffff02458471040000000008abab636a51ac0065545aa80000000000096a6553516a5263ac6a00000000", "51526300ab5363", 1, 1449668540, "ddfd902bba312a06197810da96a0ddccb595f96670b28ded7dba88d8cd0469b8"],
+	["fa4d868b024b010bd5dce46576c2fb489aa60bb797dac3c72a4836f49812c5c564c258414f03000000007a9b3a585e05027bdd89edbadf3c85ac61f8c3a04c773fa746517ae600ff1a9d6b6c02fb0200000004515163abffffffff01b17d020500000000046a65520000000000", "536565ab65635363", 0, -1718953372, "96c2b32f0a00a5925db7ba72d0b5d39922f30ea0f7443b22bc1b734808513c47"],
+	["cac6382d0462375e83b67c7a86c922b569a7473bfced67f17afd96c3cd2d896cf113febf9e0300000003006a53ffffffffaa4913b7eae6821487dd3ca43a514e94dcbbf350f8cc4cafff9c1a88720711b800000000096a6a525300acac6353ffffffff184fc4109c34ea27014cc2c1536ef7ed1821951797a7141ddacdd6e429fae6ff01000000055251655200ffffffff9e7b79b4e6836e290d7b489ead931cba65d1030ccc06f20bd4ca46a40195b33c030000000008f6bc8304a09a2704000000000563655353511dbc73050000000000cf34c500000000000091f76e0000000000085200ab00005100abd07208cb", "0063656a", 2, -1488731031, "bf078519fa87b79f40abc38f1831731422722c59f88d86775535f209cb41b9b1"],
+	["1711146502c1a0b82eaa7893976fefe0fb758c3f0e560447cef6e1bde11e42de91a125f71c030000000015bd8c04703b4030496c7461482481f290c623be3e76ad23d57a955807c9e851aaaa20270300000000d04abaf20326dcb7030000000001632225350400000000075263ac00520063dddad9020000000000af23d148", "52520053510063", 0, 1852122830, "e33d5ee08c0f3c130a44d7ce29606450271b676f4a80c52ab9ffab00cecf67f8"],
+	["8d5b124d0231fbfc640c706ddb1d57bb49a18ba8ca0e1101e32c7e6e65a0d4c7971d93ea360100000008acabac0000abac65ffffffff8fe0fd7696597b845c079c3e7b87d4a44110c445a330d70342a5501955e17dd70100000004ab525363ef22e8a90346629f030000000009516a00ac63acac51657bd57b05000000000200acfd4288050000000009acab5352ab00ab636300000000", "53ac526553ab65", 0, 1253152975, "8b57a7c3170c6c02dd14ae1d392ce3d828197b20e9145c89c1cfd5de050e1562"],
+	["38146dc502c7430e92b6708e9e107b61cd38e5e773d9395e5c8ad8986e7e4c03ee1c1e1e760100000000c8962ce2ac1bb3b1285c0b9ba07f4d2e5ce87c738c42ac0548cd8cec1100e6928cd6b0b6010000000763ab636aab52527cccefbd04e5f6f8020000000006006aabacac65ab2c4a00000000000351635209a6f40100000000026aacce57dc040000000008ab5353ab516a516a00000000", "ab", 0, -1205978252, "3cb5b030e7da0b60ccce5b4a7f3793e6ca56f03e3799fe2d6c3cc22d6d841dcb"],
+	["22d81c740469695a6a83a9a4824f77ecff8804d020df23713990afce2b72591ed7de98500502000000065352526a6a6affffffff90dc85e118379b1005d7bbc7d2b8b0bab104dad7eaa49ff5bead892f17d8c3ba010000000665656300ab51ffffffff965193879e1d5628b52005d8560a35a2ba57a7f19201a4045b7cbab85133311d0200000003ac005348af21a13f9b4e0ad90ed20bf84e4740c8a9d7129632590349afc03799414b76fd6e826200000000025353ffffffff04a0d40d04000000000060702700000000000652655151516ad31f1502000000000365ac0069a1ac0500000000095100655300ab53525100000000", "51636a52ac", 0, -1644680765, "add7f5da27262f13da6a1e2cc2feafdc809bd66a67fb8ae2a6f5e6be95373b6f"],
+	["a27dcbc801e3475174a183586082e0914c314bc9d79d1570f29b54591e5e0dff07fbb45a7f0000000004ac53ab51ffffffff027347f5020000000005535351ab63d0e5c9030000000009ac65ab6a63515200ab7cd632ed", "ac63636553", 0, -686435306, "883a6ea3b2cc53fe8a803c229106366ca14d25ffbab9fef8367340f65b201da6"],
+	["b123ed2204410d4e8aaaa8cdb95234ca86dad9ff77fb4ae0fd4c06ebed36794f0215ede0040100000002ac63ffffffff3b58b81b19b90d8f402701389b238c3a84ff9ba9aeea298bbf15b41a6766d27a01000000056a6553ab00151824d401786153b819831fb15926ff1944ea7b03d884935a8bde01ed069d5fd80220310200000000ffffffffa9c9d246f1eb8b7b382a9032b55567e9a93f86c77f4e32c092aa1738f7f756c30100000002ab65ffffffff011a2b48000000000000ed44d1fb", "630051ab63", 2, -1118263883, "b5dab912bcabedff5f63f6dd395fc2cf030d83eb4dd28214baba68a45b4bfff0"],
+	["1339051503e196f730955c5a39acd6ed28dec89b4dadc3f7c79b203b344511270e5747fa9900000000045151636affffffff378c6090e08a3895cedf1d25453bbe955a274657172491fd2887ed5c9aceca7b0100000000ffffffffcf7cc3c36ddf9d4749edfa9cefed496d2f86e870deb814bfcd3b5637a5496461030000000451006300ffffffff04dcf3fa010000000008526a63005263acabb41d84040000000004abac5153800eff020000000005656a535365106c5e00000000000000000000", "abac5300", 2, 2013719928, "7fc74de39ce6ca46ca25d760d3cec7bb21fd14f7efe1c443b5aa294f2cb5f546"],
+	["0728c606014c1fd6005ccf878196ba71a54e86cc8c53d6db500c3cc0ac369a26fac6fcbc210000000005ab53ac5365ba9668290182d7870100000000066a000053655100000000", "65", 0, 1789961588, "ab6baa6da3b2bc853868d166f8996ad31d63ef981179f9104f49968fd61c8427"],
+	["a1134397034bf4067b6c81c581e2b73fb63835a08819ba24e4e92df73074bf773c94577df7000000000465525251ffffffff8b6608feaa3c1f35f49c6330a769716fa01c5c6f6e0cdc2eb10dfc99bbc21e77010000000952656aac005352655180a0bda4bc72002c2ea8262e26e03391536ec36867258cab968a6fd6ec7523b64fa1d8c001000000056a53ac6353ffffffff04dbeeed05000000000553650052abcd5d0e01000000000463abab51104b2e0500000000066aac53ac5165283ca7010000000004535252ab00000000", "ab515151516552ab", 1, -324598676, "91178482112f94d1c8e929de443e4b9c893e18682998d393ca9ca77950412586"],
+	["bcdafbae04aa18eb75855aeb1f5124f30044741351b33794254a80070940cb10552fa4fa8e0300000001acd0423fe6e3f3f88ae606f2e8cfab7a5ef87caa2a8f0401765ff9a47d718afcfb40c0099b0000000008ac6565ab53ac6aac645308009d680202d600e492b31ee0ab77c7c5883ebad5065f1ce87e4dfe6453e54023a0010000000151ffffffffb9d818b14245899e1d440152827c95268a676f14c3389fc47f5a11a7b38b1bde03000000026300ffffffff03cda22102000000000751ac535263005100a4d20400000000045200536ac8bef405000000000700ab51ab6563ac00000000", "6553516a526aab", 1, -2111409753, "5e1849e7368cf4f042718586d9bd831d61479b775bab97aba9f450042bd9876a"],
+	["ed3bb93802ddbd08cb030ef60a2247f715a0226de390c9c1a81d52e83f8674879065b5f87d0300000003ab6552ffffffff04d2c5e60a21fb6da8de20bf206db43b720e2a24ce26779bca25584c3f765d1e0200000008ab656a6aacab00ab6e946ded025a811d04000000000951abac6352ac00ab5143cfa3030000000005635200636a00000000", "5352ac650065535300", 1, -668727133, "e9995065e1fddef72a796eef5274de62012249660dc9d233a4f24e02a2979c87"],
+	["59f4629d030fa5d115c33e8d55a79ea3cba8c209821f979ed0e285299a9c72a73c5bba00150200000002636affffffffd8aca2176df3f7a96d0dc4ee3d24e6cecde1582323eec2ebef9a11f8162f17ac0000000007ab6565acab6553ffffffffeebc10af4f99c7a21cbc1d1074bd9f0ee032482a71800f44f26ee67491208e0403000000065352ac656351ffffffff0434e955040000000004ab515152caf2b305000000000365ac007b1473030000000003ab530033da970500000000060051536a5253bb08ab51", "", 2, 396340944, "0e9c47973ef2c292b2252c623f465bbb92046fe0b893eebf4e1c9e02cb01c397"],
+	["286e3eb7043902bae5173ac3b39b44c5950bc363f474386a50b98c7bdab26f98dc83449c4a020000000752ac6a00510051ffffffff4339cd6a07f5a5a2cb5815e5845da70300f5c7833788363bf7fe67595d3225520100000000fffffffff9c2dd8b06ad910365ffdee1a966f124378a2b8021065c8764f6138bb1e951380200000005ab5153ac6affffffff0370202aba7a68df85436ea7c945139513384ef391fa33d16020420b8ad40e9a000000000900ab5165526353abacffffffff020c1907000000000004abac526a1b490b040000000000df1528f7", "5353ab", 3, -1407529517, "32154c09174a9906183abf26538c39e78468344ca0848bbd0785e24a3565d932"],
+	["2e245cf80179e2e95cd1b34995c2aff49fe4519cd7cee93ad7587f7f7e8105fc2dff206cd30200000009006a63516a6553ab52350435a201d5ed2d02000000000352ab6558552c89", "00ab53", 0, -233917810, "4605ae5fd3d50f9c45d37db7118a81a9ef6eb475d2333f59df5d3e216f150d49"],
+	["33a98004029d262f951881b20a8d746c8c707ea802cd2c8b02a33b7e907c58699f97e42be80100000007ac53536552abacdee04cc01d205fd8a3687fdf265b064d42ab38046d76c736aad8865ca210824b7c622ecf02000000070065006a536a6affffffff01431c5d010000000000270d48ee", "", 1, 921554116, "ff9d7394002f3f196ea25472ea6c46f753bd879a7244795157bb7235c9322902"],
+	["aac18f2b02b144ed481557c53f2146ae523f24fcde40f3445ab0193b6b276c315dc2894d2300000000075165650000636a233526947dbffc76aec7db1e1baa6868ad4799c76e14794dcbaaec9e713a83967f6a65170200000005abac6551ab27d518be01b652a30000000000015300000000", "52ac5353", 1, 1559377136, "59fc2959bb7bb24576cc8a237961ed95bbb900679d94da6567734c4390cb6ef5"],
+	["5ab79881033555b65fe58c928883f70ce7057426fbdd5c67d7260da0fe8b1b9e6a2674cb850300000009ac516aac6aac006a6affffffffa5be9223b43c2b1a4d120b5c5b6ec0484f637952a3252181d0f8e813e76e11580200000000e4b5ceb8118cb77215bbeedc9a076a4d087bb9cd1473ea32368b71daeeeacc451ec209010000000005acac5153aced7dc34e02bc5d11030000000005ac5363006a54185803000000000552ab00636a00000000", "5100", 1, 1927062711, "e9f53d531c12cce1c50abed4ac521a372b4449b6a12f9327c80020df6bff66c0"],
+	["6c2c8fac0124b0b7d4b610c3c5b91dee32b7c927ac71abdf2d008990ca1ac40de0dfd530660300000006ababac5253656bd7eada01d847ec000000000004ac52006af4232ec8", "6a6a6a0051", 0, -340809707, "fb51eb9d7e47d32ff2086205214f90c7c139e08c257a64829ae4d2b301071c6a"],
+	["6e3880af031735a0059c0bb5180574a7dcc88e522c8b56746d130f8d45a52184045f96793e0100000008acabac6a526a6553fffffffffe05f14cdef7d12a9169ec0fd37524b5fcd3295f73f48ca35a36e671da4a2f560000000008006a526a6351ab63ffffffffdfbd869ac9e472640a84caf28bdd82e8c6797f42d03b99817a705a24fde2736600000000010090a090a503db956b04000000000952ac53ab6a536a63ab358390010000000009656a5200525153ac65353ee204000000000763530052526aaba6ad83fb", "535151ab6300", 2, 222014018, "57a34ddeb1bf36d28c7294dda0432e9228a9c9e5cc5c692db98b6ed2e218d825"],
+	["8df1cd19027db4240718dcaf70cdee33b26ea3dece49ae6917331a028c85c5a1fb7ee3e475020000000865ab6a00510063636157988bc84d8d55a8ba93cdea001b9bf9d0fa65b5db42be6084b5b1e1556f3602f65d4d0100000005ac00ab0052206c852902b2fb54030000000008ac5252536aacac5378c4a5050000000007acabac535163532784439e", "acab6a", 0, 1105620132, "edb7c74223d1f10f9b3b9c1db8064bc487321ff7bb346f287c6bc2fad83682de"],
+	["0e803682024f79337b25c98f276d412bc27e56a300aa422c42994004790cee213008ff1b8303000000080051ac65ac655165f421a331892b19a44c9f88413d057fea03c3c4a6c7de4911fe6fe79cf2e9b3b10184b1910200000005525163630096cb1c670398277204000000000253acf7d5d502000000000963536a6a636a5363ab381092020000000002ac6a911ccf32", "6565", 1, -1492094009, "f0672638a0e568a919e9d8a9cbd7c0189a3e132940beeb52f111a89dcc2daa2c"],
+	["7d71669d03022f9dd90edac323cde9e56354c6804c6b8e687e9ae699f46805aafb8bcaa636000000000253abffffffff698a5fdd3d7f2b8b000c68333e4dd58fa8045b3e2f689b889beeb3156cecdb490300000009525353abab0051acabc53f0aa821cdd69b473ec6e6cf45cf9b38996e1c8f52c27878a01ec8bb02e8cb31ad24e500000000055353ab0052ffffffff0447a23401000000000565ab53ab5133aaa0030000000006515163656563057d110300000000056a6aacac52cf13b5000000000003526a5100000000", "6a6a51", 1, -1349253507, "722efdd69a7d51d3d77bed0ac5544502da67e475ea5857cd5af6bdf640a69945"],
+	["9ff618e60136f8e6bb7eabaaac7d6e2535f5fba95854be6d2726f986eaa9537cb283c701ff02000000026a65ffffffff012d1c0905000000000865ab00ac6a516a652f9ad240", "51515253635351ac", 0, 1571304387, "659cd3203095d4a8672646add7d77831a1926fc5b66128801979939383695a79"],
+	["9fbd43ac025e1462ecd10b1a9182a8e0c542f6d1089322a41822ab94361e214ed7e1dfdd8a020000000263519d0437581538e8e0b6aea765beff5b4f3a4a202fca6e5d19b34c141078c6688f71ba5b8e0100000003ac6552ffffffff02077774050000000009655153655263acab6a0ae4e10100000000035152524c97136b", "635152ab", 0, 1969622955, "d82d4ccd9b67810f26a378ad9592eb7a30935cbbd27e859b00981aefd0a72e08"],
+	["0117c92004314b84ed228fc11e2999e657f953b6de3b233331b5f0d0cf40d5cc149b93c7b30300000005515263516a083e8af1bd540e54bf5b309d36ba80ed361d77bbf4a1805c7aa73667ad9df4f97e2da410020000000600ab6351ab524d04f2179455e794b2fcb3d214670001c885f0802e4b5e015ed13a917514a7618f5f332203000000086a536aab51000063ecf029e65a4a009a5d67796c9f1eb358b0d4bd2620c8ad7330fb98f5a802ab92d0038b1002000000036a6551a184a88804b04490000000000009ab6a5152535165526a33d1ab020000000001518e92320000000000002913df04000000000952abac6353525353ac8b19bfdf", "000051ab0000", 0, 489433059, "8eebac87e60da524bbccaf285a44043e2c9232868dda6c6271a53c153e7f3a55"],
+	["e7f5482903f98f0299e0984b361efb2fddcd9979869102281e705d3001a9d283fe9f3f3a1e02000000025365ffffffffcc5c7fe82feebad32a22715fc30bc584efc9cd9cadd57e5bc4b6a265547e676e0000000001ab579d21235bc2281e08bf5e7f8f64d3afb552839b9aa5c77cf762ba2366fffd7ebb74e49400000000055263ab63633df82cf40100982e05000000000453ac535300000000", "acacab", 2, -1362931214, "046de666545330e50d53083eb78c9336416902f9b96c77cc8d8e543da6dfc7e4"],
+	["09adb2e90175ca0e816326ae2dce7750c1b27941b16f6278023dbc294632ab97977852a09d030000000465ab006affffffff027739cf0100000000075151ab63ac65ab8a5bb601000000000653ac5151520011313cdc", "ac", 0, -76831756, "478ee06501b4965b40bdba6cbaad9b779b38555a970912bb791b86b7191c54bc"],
+	["f973867602e30f857855cd0364b5bbb894c049f44abbfd661d7ae5dbfeaafca89fac8959c20100000005ab52536a51ffffffffbeceb68a4715f99ba50e131884d8d20f4a179313691150adf0ebf29d05f8770303000000066352ab00ac63ffffffff021fddb90000000000036a656322a177000000000008526500ac5100acac84839083", "52acab53ac", 0, 1407879325, "db0329439490efc64b7104d6d009b03fbc6fac597cf54fd786fbbb5fd73b92b4"],
+	["fd22ebaa03bd588ad16795bea7d4aa7f7d48df163d75ea3afebe7017ce2f350f6a0c1cb0bb00000000086aabac5153526363ffffffff488e0bb22e26a565d77ba07178d17d8f85702630ee665ec35d152fa05af3bda10200000004515163abffffffffeb21035849e85ad84b2805e1069a91bb36c425dc9c212d9bae50a95b6bfde1200300000001ab5df262fd02b69848040000000008ab6363636a6363ace23bf2010000000007655263635253534348c1da", "006353526563516a00", 0, -1491036196, "92364ba3c7a85d4e88885b8cb9b520dd81fc29e9d2b750d0790690e9c1246673"],
+	["130b462d01dd49fac019dc4442d0fb54eaa6b1c2d1ad0197590b7df26969a67abd7f3fbb4f0100000008ac65abac53ab6563ffffffff0345f825000000000004ac53acac9d5816020000000002ababeff8e90500000000086aab006552ac6a53a892dc55", "ab0065ac530052", 0, 944483412, "1f4209fd4ce7f13d175fdd522474ae9b34776fe11a5f17a27d0796c77a2a7a9d"],
+	["f8e50c2604609be2a95f6d0f31553081f4e1a49a0a30777fe51eb1c596c1a9a92c053cf28c0300000009656a51ac5252630052fffffffff792ed0132ae2bd2f11d4a2aab9d0c4fbdf9a66d9ae2dc4108afccdc14d2b1700100000007ab6a6563ac636a7bfb2fa116122b539dd6a2ab089f88f3bc5923e5050c8262c112ff9ce0a3cd51c6e3e84f02000000066551ac5352650d5e687ddf4cc9a497087cabecf74d236aa4fc3081c3f67b6d323cba795e10e7a171b725000000000852635351ab635100ffffffff02df5409020000000008ac6a53acab5151004156990200000000045163655200000000", "ac53abac65005300", 0, -173065000, "b596f206d7eba22b7e2d1b7a4f4cf69c7c541b6c84dcc943f84e19a99a923310"],
+	["18020dd1017f149eec65b2ec23300d8df0a7dd64fc8558b36907723c03cd1ba672bbb0f51d0300000005ab65ab6a63ffffffff037cd7ae000000000009ab516a65005352ac65f1e4360400000000056353530053f118f0040000000009536363ab006500abac00000000", "63ab51acab52ac", 0, -550412404, "e19b796c14a0373674968e342f2741d8b51092a5f8409e9bff7dcd52e56fcbcb"],
+	["b04154610363fdade55ceb6942d5e5a723323863b48a0cb04fdcf56210717955763f56b08d0300000009ac526a525151635151ffffffff93a176e76151a9eabdd7af00ef2af72f9e7af5ecb0aa4d45d00618f394cdd03c030000000074d818b332ebe05dc24c44d776cf9d275c61f471cc01efce12fd5a16464157f1842c65cb00000000066a0000ac6352d3c4134f01d8a1c0030000000005520000005200000000", "5200656a656351", 2, -9757957, "6e3e5ba77f760b6b5b5557b13043f1262418f3dd2ce7f0298b012811fc8ad5bc"],
+	["9794b3ce033df7b1e32db62d2f0906b589eacdacf5743963dc2255b6b9a6cba211fadd0d41020000000600ab00650065ffffffffaae00687a6a4131152bbcaafedfaed461c86754b0bde39e2bef720e6d1860a0302000000070065516aac6552ffffffff50e4ef784d6230df7486e972e8918d919f005025bc2d9aacba130f58bed7056703000000075265ab52656a52ffffffff02c6f1a9000000000006005251006363cf450c040000000008abab63510053abac00000000", "ac0063ababab515353", 1, 2063905082, "fad092fc98f17c2c20e10ba9a8eb44cc2bcc964b006f4da45cb9ceb249c69698"],
+	["94533db7015e70e8df715066efa69dbb9c3a42ff733367c18c22ff070392f988f3b93920820000000006535363636300ce4dac3e03169af80300000000080065ac6a53ac65ac39c050020000000006abacab6aacac708a02050000000005ac5251520000000000", "6553", 0, -360458507, "5418cf059b5f15774836edd93571e0eed3855ba67b2b08c99dccab69dc87d3e9"],
+	["c8597ada04f59836f06c224a2640b79f3a8a7b41ef3efa2602592ddda38e7597da6c639fee0300000009005251635351acabacffffffff4c518f347ee694884b9d4072c9e916b1a1f0a7fc74a1c90c63fdf8e5a185b6ae02000000007113af55afb41af7518ea6146786c7c726641c68c8829a52925e8d4afd07d8945f68e7230300000008ab00ab65ab650063ffffffffc28e46d7598312c420e11dfaae12add68b4d85adb182ae5b28f8340185394b63000000000165ffffffff04dbabb7010000000000ee2f6000000000000852ab6500ab6a51acb62a27000000000009ac53515300ac006a6345fb7505000000000752516a0051636a00000000", "", 3, 15199787, "0d66003aff5bf78cf492ecbc8fd40c92891acd58d0a271be9062e035897f317e"],
+	["1a28c4f702c8efaad96d879b38ec65c5283b5c084b819ad7db1c086e85e32446c7818dc7a90300000008656351536a525165fa78cef86c982f1aac9c5eb8b707aee8366f74574c8f42ef240599c955ef4401cf578be30200000002ab518893292204c430eb0100000000016503138a0300000000040053abac60e0eb010000000005525200ab63567c2d030000000004abab52006cf81e85", "ab51525152", 1, 2118315905, "4e4c9a781f626b59b1d3ad8f2c488eb6dee8bb19b9bc138bf0dc33e7799210d4"],
+	["c6c7a87003f772bcae9f3a0ac5e499000b68703e1804b9ddc3e73099663564d53ddc4e1c6e01000000076a536a6aac63636e3102122f4c30056ef8711a6bf11f641ddfa6984c25ac38c3b3e286e74e839198a80a34010000000165867195cd425821dfa2f279cb1390029834c06f018b1e6af73823c867bf3a0524d1d6923b0300000005acab53ab65ffffffff02fa4c49010000000008ab656a0052650053e001100400000000008836d972", "ac526351acab", 1, 978122815, "a869c18a0edf563d6e5eddd5d5ae8686f41d07f394f95c9feb8b7e52761531ca"],
+	["0ea580ac04c9495ab6af3b8d59108bb4194fcb9af90b3511c83f7bb046d87aedbf8423218e02000000085152acac006363ab9063d7dc25704e0caa5edde1c6f2dd137ded379ff597e055b2977b9c559b07a7134fcef2000000000200aca89e50181f86e9854ae3b453f239e2847cf67300fff802707c8e3867ae421df69274449402000000056365abababffffffff47a4760c881a4d7e51c69b69977707bd2fb3bcdc300f0efc61f5840e1ac72cee0000000000ffffffff0460179a020000000004ab53ab52a5250c0500000000096565acac6365ab52ab6c281e02000000000952635100ac006563654e55070400000000046552526500000000", "ab526563acac53ab", 2, 1426964167, "b1c50d58b753e8f6c7513752158e9802cf0a729ebe432b99acc0fe5d9b4e9980"],
+	["c33028b301d5093e1e8397270d75a0b009b2a6509a01861061ab022ca122a6ba935b8513320200000000ffffffff013bcf5a0500000000015200000000", "", 0, -513413204, "6b1459536f51482f5dbf42d7e561896557461e1e3b6bf67871e2b51faae2832c"],
+	["43b2727901a7dd06dd2abf690a1ccedc0b0739cb551200796669d9a25f24f71d8d101379f50300000000ffffffff0418e031040000000000863d770000000000085352ac526563ac5174929e040000000004ac65ac00ec31ac0100000000066a51ababab5300000000", "65", 0, -492874289, "154ff7a9f0875edcfb9f8657a0b98dd9600fabee3c43eb88af37cf99286d516c"],
+	["4763ed4401c3e6ab204bed280528e84d5288f9cac5fb8a2e7bd699c7b98d4df4ac0c40e55303000000066a6aacab5165ffffffff015b57f80400000000046a63535100000000", "ac51abab53", 0, -592611747, "849033a2321b5755e56ef4527ae6f51e30e3bca50149d5707368479723d744f8"],
+	["d24f647b02f71708a880e6819a1dc929c1a50b16447e158f8ff62f9ccd644e0ca3c592593702000000050053536a00ffffffff67868cd5414b6ca792030b18d649de5450a456407242b296d936bcf3db79e07b02000000005af6319c016022f50100000000036a516300000000", "6aab526353516a6a", 0, 1350782301, "8556fe52d1d0782361dc28baaf8774b13f3ce5ed486ae0f124b665111e08e3e3"],
+	["fe6ddf3a02657e42a7496ef170b4a8caf245b925b91c7840fd28e4a22c03cb459cb498b8d603000000065263656a650071ce6bf8d905106f9f1faf6488164f3decac65bf3c5afe1dcee20e6bc3cb6d052561985a030000000163295b117601343dbb0000000000026563dba521df", "", 1, -1696179931, "d9684685c99ce48f398fb467a91a1a59629a850c429046fb3071f1fa9a5fe816"],
+	["c61523ef0129bb3952533cbf22ed797fa2088f307837dd0be1849f20decf709cf98c6f032f03000000026563c0f1d378044338310400000000066363516a5165a14fcb0400000000095163536a6a00ab53657271d60200000000001d953f0500000000010000000000", "53516353005153", 0, 1141615707, "7e975a72db5adaa3c48d525d9c28ac11cf116d0f8b16ce08f735ad75a80aec66"],
+	["ba3dac6c0182562b0a26d475fe1e36315f0913b6869bdad0ecf21f1339a5fcbccd32056c840200000000ffffffff04300351050000000000220ed405000000000851abac636565ac53dbbd19020000000007636363ac6a52acbb005a0500000000016abd0c78a8", "63006a635151005352", 0, 1359658828, "47bc8ab070273e1f4a0789c37b45569a6e16f3f3092d1ce94dddc3c34a28f9f4"],
+	["ac27e7f5025fc877d1d99f7fc18dd4cadbafa50e34e1676748cc89c202f93abf36ed46362101000000036300abffffffff958cd5381962b765e14d87fc9524d751e4752dd66471f973ed38b9d562e525620100000003006500ffffffff02b67120050000000004ac51516adc330c0300000000015200000000", "656352", 1, 15049991, "f3374253d64ac264055bdbcc32e27426416bd595b7c7915936c70f839e504010"],
+	["edb30140029182b80c8c3255b888f7c7f061c4174d1db45879dca98c9aab8c8fed647a6ffc03000000086a53510052ab6300ffffffff82f65f261db62d517362c886c429c8fbbea250bcaad93356be6f86ba573e9d930100000000ffffffff04daaf150400000000016a86d1300100000000096a6353535252ac5165d4ddaf000000000002abab5f1c6201000000000000000000", "ab6a6a00ac", 0, -2058017816, "8d7794703dad18e2e40d83f3e65269834bb293e2d2b8525932d6921884b8f368"],
+	["7e50207303146d1f7ad62843ae8017737a698498d4b9118c7a89bb02e8370307fa4fada41d000000000753006300005152b7afefc85674b1104ba33ef2bf37c6ed26316badbc0b4aa6cb8b00722da4f82ff3555a6c020000000900ac656363ac51ac52ffffffff93fab89973bd322c5d7ad7e2b929315453e5f7ada3072a36d8e33ca8bebee6e0020000000300acab930da52b04384b04000000000004650052ac435e380200000000076a6a515263ab6aa9494705000000000600ab6a525252af8ba90100000000096565acab526353536a279b17ad", "acac005263536aac63", 1, -34754133, "4e6357da0057fb7ff79da2cc0f20c5df27ff8b2f8af4c1709e6530459f7972b0"],
+	["c05764f40244fb4ebe4c54f2c5298c7c798aa90e62c29709acca0b4c2c6ec08430b26167440100000008acab6a6565005253ffffffffc02c2418f398318e7f34a3cf669d034eef2111ea95b9f0978b01493293293a870100000000e563e2e00238ee8d040000000002acab03fb060200000000076500ac656a516aa37f5534", "52ab6a0065", 1, -2033176648, "83deef4a698b62a79d4877dd9afebc3011a5275dbe06e89567e9ef84e8a4ee19"],
+	["5a59e0b9040654a3596d6dab8146462363cd6549898c26e2476b1f6ae42915f73fd9aedfda00000000036363abffffffff9ac9e9ca90be0187be2214251ff08ba118e6bf5e2fd1ba55229d24e50a510d53010000000165ffffffff41d42d799ac4104644969937522873c0834cc2fcdab7cdbecd84d213c0e96fd60000000000ffffffffd838db2c1a4f30e2eaa7876ef778470f8729fcf258ad228b388df2488709f8410300000000fdf2ace002ceb6d903000000000265654c1310040000000003ac00657e91c0ec", "536a63ac", 0, 82144555, "98ccde2dc14d14f5d8b1eeea5364bd18fc84560fec2fcea8de4d88b49c00695e"],
+	["156ebc8202065d0b114984ee98c097600c75c859bfee13af75dc93f57c313a877efb09f230010000000463536a51ffffffff81114e8a697be3ead948b43b5005770dd87ffb1d5ccd4089fa6c8b33d3029e9c03000000066a5251656351ffffffff01a87f140000000000050000ac51ac00000000", "00", 0, -362221092, "a903c84d8c5e71134d1ab6dc1e21ac307c4c1a32c90c90f556f257b8a0ec1bf5"],
+	["15e37793023c7cbf46e073428908fce0331e49550f2a42b92468827852693f0532a01c29f70200000007005353636351acffffffff38426d9cec036f00eb56ec1dcd193647e56a7577278417b8a86a78ac53199bc403000000056353006a53ffffffff04a25ce103000000000900ab5365656a526a63c8eff7030000000004526353537ab6db0200000000016a11a3fa02000000000651acacab526500000000", "53ac6aab6a6551", 0, 1117532791, "83c68b3c5a89260ce16ce8b4dbf02e1f573c532d9a72f5ea57ab419fa2630214"],
+	["f7a09f10027250fc1b70398fb5c6bffd2be9718d3da727e841a73596fdd63810c9e4520a6a010000000963ac516a636a65acac1d2e2c57ab28d311edc4f858c1663972eebc3bbc93ed774801227fda65020a7ec1965f780200000005ac5252516a8299fddc01dcbf7200000000000463ac6551960fda03", "65acab51", 1, 2017321737, "9c5fa02abfd34d0f9dec32bf3edb1089fca70016debdb41f4f54affcb13a2a2a"],
+	["6d97a9a5029220e04f4ccc342d8394c751282c328bf1c132167fc05551d4ca4da4795f6d4e02000000076a0052ab525165ffffffff9516a205e555fa2a16b73e6db6c223a9e759a7e09c9a149a8f376c0a7233fa1b0100000007acab51ab63ac6affffffff04868aed04000000000652ac65ac536a396edf01000000000044386c0000000000076aab5363655200894d48010000000001ab8ebefc23", "6351526aac51", 1, 1943666485, "f0bd4ca8e97203b9b4e86bc24bdc8a1a726db5e99b91000a14519dc83fc55c29"],
+	["8e3fddfb028d9e566dfdda251cd874cd3ce72e9dde837f95343e90bd2a93fe21c5daeb5eed01000000045151525140517dc818181f1e7564b8b1013fd68a2f9a56bd89469686367a0e72c06be435cf99db750000000003635251ffffffff01c051780300000000096552ababac6a65acab099766eb", "5163ab6a52ababab51", 1, 1296295812, "5509eba029cc11d7dd2808b8c9eb47a19022b8d8b7778893459bbc19ab7ea820"],
+	["a603f37b02a35e5f25aae73d0adc0b4b479e68a734cf722723fd4e0267a26644c36faefdab0200000000ffffffff43374ad26838bf733f8302585b0f9c22e5b8179888030de9bdda180160d770650200000001004c7309ce01379099040000000005526552536500000000", "abababab005153", 0, 1409936559, "4ca73da4fcd5f1b10da07998706ffe16408aa5dff7cec40b52081a6514e3827e"],
+	["9eeedaa8034471a3a0e3165620d1743237986f060c4434f095c226114dcb4b4ec78274729f03000000086a5365510052ac6afb505af3736e347e3f299a58b1b968fce0d78f7457f4eab69240cbc40872fd61b5bf8b120200000002ac52df8247cf979b95a4c97ecb8edf26b3833f967020cd2fb25146a70e60f82c9ee4b14e88b103000000008459e2fa0125cbcd05000000000000000000", "52ab5352006353516a", 0, -1832576682, "fb018ae54206fdd20c83ae5873ec82b8e320a27ed0d0662db09cda8a071f9852"],
+	["05921d7c048cf26f76c1219d0237c226454c2a713c18bf152acc83c8b0647a94b13477c07f0300000003ac526afffffffff2f494453afa0cabffd1ba0a626c56f90681087a5c1bd81d6adeb89184b27b7402000000036a6352ffffffff0ad10e2d3ce355481d1b215030820da411d3f571c3f15e8daf22fe15342fed04000000000095f29f7b93ff814a9836f54dc6852ec414e9c4e16a506636715f569151559100ccfec1d100000000055263656a53ffffffff04f4ffef010000000008ac6a6aabacabab6a0e6689040000000006ab536a5352abe364d005000000000965536363655251ab53807e00010000000004526aab63f18003e3", "6363ac51", 3, -375891099, "001b0b176f0451dfe2d9787b42097ceb62c70d324e925ead4c58b09eebdf7f67"],
+	["b9b44d9f04b9f15e787d7704e6797d51bc46382190c36d8845ec68dfd63ee64cf7a467b21e00000000096aac00530052ab636aba1bcb110a80c5cbe073f12c739e3b20836aa217a4507648d133a8eedd3f02cb55c132b203000000076a000063526352b1c288e3a9ff1f2da603f230b32ef7c0d402bdcf652545e2322ac01d725d75f5024048ad0100000000ffffffffffd882d963be559569c94febc0ef241801d09dc69527c9490210f098ed8203c700000000056a006300ab9109298d01719d9a0300000000066a52ab006365d7894c5b", "ac6351650063636a", 3, -622355349, "ac87b1b93a6baab6b2c6624f10e8ebf6849b0378ef9660a3329073e8f5553c8d"],
+	["ff60473b02574f46d3e49814c484081d1adb9b15367ba8487291fc6714fd6e3383d5b335f001000000026a6ae0b82da3dc77e5030db23d77b58c3c20fa0b70aa7d341a0f95f3f72912165d751afd57230300000008ac536563516a6363ffffffff04f86c0200000000000553acab636ab13111000000000003510065f0d3f305000000000951ab516a65516aabab730a3a010000000002515200000000", "ac6a", 1, 1895032314, "0767e09bba8cd66d55915677a1c781acd5054f530d5cf6de2d34320d6c467d80"],
+	["f218026204f4f4fc3d3bd0eada07c57b88570d544a0436ae9f8b753792c0c239810bb30fbc0200000002536affffffff8a468928d6ec4cc10aa0f73047697970e99fa64ae8a3b4dca7551deb0b639149010000000851ab520052650051ffffffffa98dc5df357289c9f6873d0f5afcb5b030d629e8f23aa082cf06ec9a95f3b0cf0000000000ffffffffea2c2850c5107705fd380d6f29b03f533482fd036db88739122aac9eff04e0aa010000000365536a03bd37db034ac4c4020000000007515152655200ac33b27705000000000151efb71e0000000000007b65425b", "515151", 3, -1772252043, "de35c84a58f2458c33f564b9e58bc57c3e028d629f961ad1b3c10ee020166e5a"],
+	["48e7d42103b260b27577b70530d1ac2fed2551e9dd607cbcf66dca34bb8c03862cf8f5fd5401000000075151526aacab00ffffffff1e3d3b841552f7c6a83ee379d9d66636836673ce0b0eda95af8f2d2523c91813030000000665acac006365ffffffff388b3c386cd8c9ef67c83f3eaddc79f1ff910342602c9152ffe8003bce51b28b0100000008636363006a636a52ffffffff04b8f67703000000000852005353ac6552520cef720200000000085151ab6352ab00ab5096d6030000000005516a005100662582020000000001ac6c137280", "6a65", 1, 1513618429, "e2fa3e1976aed82c0987ab30d4542da2cb1cffc2f73be13480132da8c8558d5c"],
+	["91ebc4cf01bc1e068d958d72ee6e954b196f1d85b3faf75a521b88a78021c543a06e056279000000000265ab7c12df0503832121030000000000cc41a6010000000005ab5263516540a951050000000006ab63ab65acac00000000", "526a0065636a6a6aac", 0, -614046478, "7de4ba875b2e584a7b658818c112e51ee5e86226f5a80e5f6b15528c86400573"],
+	["3cd4474201be7a6c25403bf00ca62e2aa8f8f4f700154e1bb4d18c66f7bb7f9b975649f0dc0100000006535151535153ffffffff01febbeb000000000006005151006aac00000000", "", 0, -1674687131, "6b77ca70cc452cc89acb83b69857cda98efbfc221688fe816ef4cb4faf152f86"],
+	["92fc95f00307a6b3e2572e228011b9c9ed41e58ddbaefe3b139343dbfb3b34182e9fcdc3f50200000002acab847bf1935fde8bcfe41c7dd99683289292770e7f163ad09deff0e0665ed473cd2b56b0f40300000006516551ab6351294dab312dd87b9327ce2e95eb44b712cfae0e50fda15b07816c8282e8365b643390eaab01000000026aacffffffff016e0b6b040000000001ac00000000", "650065acac005300", 2, -1885164012, "bd7d26bb3a98fc8c90c972500618bf894cb1b4fe37bf5481ff60eef439d3b970"],
+	["4db591ab018adcef5f4f3f2060e41f7829ce3a07ea41d681e8cb70a0e37685561e4767ac3b0000000005000052acabd280e63601ae6ef20000000000036a636326c908f7", "ac6a51526300630052", 0, 862877446, "355ccaf30697c9c5b966e619a554d3323d7494c3ea280a9b0dfb73f953f5c1cb"],
+	["503fd5ef029e1beb7b242d10032ac2768f9a1aca0b0faffe51cec24770664ec707ef7ede4f01000000045253ac53375e350cc77741b8e96eb1ce2d3ca91858c052e5f5830a0193200ae2a45b413dda31541f0000000003516553ffffffff0175a5ba0500000000015200000000", "6aab65510053ab65", 1, 1603081205, "353ca9619ccb0210ae18b24d0e57efa7abf8e58fa6f7102738e51e8e72c9f0c4"],
+	["c80abebd042cfec3f5c1958ee6970d2b4586e0abec8305e1d99eb9ee69ecc6c2cbd76374380000000007ac53006300ac510acee933b44817db79320df8094af039fd82111c7726da3b33269d3820123694d849ee5001000000056a65ab526562699bea8530dc916f5d61f0babea709dac578774e8a4dcd9c640ec3aceb6cb2443f24f302000000020063ea780e9e57d1e4245c1e5df19b4582f1bf704049c5654f426d783069bcc039f2d8fa659f030000000851ab53635200006a8d00de0b03654e8500000000000463ab635178ebbb0400000000055100636aab239f1d030000000006ab006300536500000000", "6565ac515100", 3, 1460851377, "b35bb1b72d02fab866ed6bbbea9726ab32d968d33a776686df3ac16aa445871e"],
+	["0337b2d5043eb6949a76d6632b8bb393efc7fe26130d7409ef248576708e2d7f9d0ced9d3102000000075352636a5163007034384dfa200f52160690fea6ce6c82a475c0ef1caf5c9e5a39f8f9ddc1c8297a5aa0eb02000000026a51ffffffff38e536298799631550f793357795d432fb2d4231f4effa183c4e2f61a816bcf0030000000463ac5300706f1cd3454344e521fde05b59b96e875c8295294da5d81d6cc7efcfe8128f150aa54d6503000000008f4a98c704c1561600000000000072cfa6000000000000e43def01000000000100cf31cc0500000000066365526a6500cbaa8e2e", "", 3, 2029506437, "7615b4a7b3be865633a31e346bc3db0bcc410502c8358a65b8127089d81b01f8"],
+	["59f6cffd034733f4616a20fe19ea6aaf6abddb30b408a3a6bd86cd343ab6fe90dc58300cc90200000000ffffffffc835430a04c3882066abe7deeb0fa1fdaef035d3233460c67d9eabdb05e95e5a02000000080065ac535353ab00ffffffff4b9a043e89ad1b4a129c8777b0e8d87a014a0ab6a3d03e131c27337bbdcb43b402000000066a5100abac6ad9e9bf62014bb118010000000001526cbe484f", "ab526352ab65", 0, 2103515652, "4f2ccf981598639bec57f885b4c3d8ea8db445ea6e61cfd45789c69374862e5e"],
+	["cbc79b10020b15d605680a24ee11d8098ad94ae5203cb6b0589e432832e20c27b72a926af20300000006ab65516a53acbb854f3146e55c508ece25fa3d99dbfde641a58ed88c051a8a51f3dacdffb1afb827814b02000000026352c43e6ef30302410a020000000000ff4bd90100000000065100ab63000008aa8e0400000000095265526565ac5365abc52c8a77", "53526aac0051", 0, 202662340, "984efe0d8d12e43827b9e4b27e97b3777ece930fd1f589d616c6f9b71dab710e"],
+	["7c07419202fa756d29288c57b5c2b83f3c847a807f4a9a651a3f6cd6c46034ae0aa3a7446b0200000004ab6a6365ffffffff9da83cf4219bb96c76f2d77d5df31c1411a421171d9b59ec02e5c1218f29935403000000008c13879002f8b1ac0400000000086a63536a636553653c584f02000000000000000000", "abac53ab656363", 1, -1038419525, "4a74f365a161bc6c9bddd249cbd70f5dadbe3de70ef4bd745dcb6ee1cd299fbd"],
+	["351cbb57021346e076d2a2889d491e9bfa28c54388c91b46ee8695874ad9aa576f1241874d0200000008ab6563525300516affffffffe13e61b8880b8cd52be4a59e00f9723a4722ea58013ec579f5b3693b9e115b1100000000096363abac5252635351ffffffff027fee02040000000008ab6a5200ab006a65b85f130200000000086a52630053ab52ab00000000", "ab6aab65", 1, 586415826, "08bbb746a596991ab7f53a76e19acad087f19cf3e1db54054aab403c43682d09"],
+	["a8252ea903f1e8ff953adb16c1d1455a5036222c6ea98207fc21818f0ece2e1fac310f9a0100000000095163ac635363ac0000be6619e9fffcde50a0413078821283ce3340b3993ad00b59950bae7a9f931a9b0a3a035f010000000463005300b8b0583fbd6049a1715e7adacf770162811989f2be20af33f5f60f26eba653dc26b024a00000000006525351636552ffffffff046d2acc030000000002636a9a2d430500000000080065005165ab53abecf63204000000000052b9ed050000000008acacac53ab65656500000000", "65ab53635253636a51", 2, 1442639059, "8ca11838775822f9a5beee57bdb352f4ee548f122de4a5ca61c21b01a1d50325"],
+	["2f1a425c0471a5239068c4f38f9df135b1d24bf52d730d4461144b97ea637504495aec360801000000055300515365c71801dd1f49f376dd134a9f523e0b4ae611a4bb122d8b26de66d95203f181d09037974300000000025152ffffffff9bdcea7bc72b6e5262e242c94851e3a5bf8f314b3e5de0e389fc9e5b3eadac030000000009525265655151005153ffffffffdbb53ce99b5a2320a4e6e2d13b01e88ed885a0957d222e508e9ec8e4f83496cb0200000007635200abac63ac04c96237020cc5490100000000080000516a51ac6553074a360200000000025152225520ca", "6551ab65ac65516a", 1, -489869549, "9bc5bb772c553831fb40abe466074e59a469154679c7dee042b8ea3001c20393"],
+	["ef3acfd4024defb48def411b8f8ba2dc408dc9ee97a4e8bde4d6cb8e10280f29c98a6e8e9103000000035100513d5389e3d67e075469dfd9f204a7d16175653a149bd7851619610d7ca6eece85a516b2df0300000005516aac6552ca678bdf02f477f003000000000057e45b0300000000055252525252af35c20a", "5165ac53ab", 1, -1900839569, "78eb6b24365ac1edc386aa4ffd15772f601059581c8776c34f92f8a7763c9ccf"],
+	["ff4468dc0108475fc8d4959a9562879ce4ab4867a419664bf6e065f17ae25043e6016c70480100000000ffffffff02133c6f0400000000000bd0a8020000000004006a520035afa4f6", "51ac65ab", 0, -537664660, "f6da59b9deac63e83728850ac791de61f5dfcaeed384ebcbb20e44afcd8c8910"],
+	["4e8594d803b1d0a26911a2bcdd46d7cbc987b7095a763885b1a97ca9cbb747d32c5ab9aa91030000000353ac53a0cc4b215e07f1d648b6eeb5cdbe9fa32b07400aa773b9696f582cebfd9930ade067b2b200000000060065abab6500fc99833216b8e27a02defd9be47fafae4e4a97f52a9d2a210d08148d2a4e5d02730bcd460100000004516351ac37ce3ae1033baa55040000000006006a636a63acc63c990400000000025265eb1919030000000005656a6a516a00000000", "", 1, -75217178, "04c5ee48514cd033b82a28e336c4d051074f477ef2675ce0ce4bafe565ee9049"],
+	["a88830a7023f13ed19ab14fd757358eb6af10d6520f9a54923a6d613ac4f2c11e249cda8aa030000000851630065abababacffffffff8f5fe0bc04a33504c4b47e3991d25118947a0261a9fa520356731eeabd561dd3020000000363ababffffffff038404bd010000000008ab5153516aab6a63d33a5601000000000263004642dc020000000009655152acac636352004be6f3af", "5253536565006aab6a", 0, 1174417836, "2e42ead953c9f4f81b72c27557e6dc7d48c37ff2f5c46c1dbe9778fb0d79f5b2"],
+	["44e1a2b4010762af23d2027864c784e34ef322b6e24c70308a28c8f2157d90d17b99cd94a401000000085163656565006300ffffffff0198233d020000000002000000000000", "52525153656365", 0, 1119696980, "d9096de94d70c6337da6202e6e588166f31bff5d51bb5adc9468594559d65695"],
+	["44ca65b901259245abd50a745037b17eb51d9ce1f41aa7056b4888285f48c6f26cb97b7a25020000000552636363abffffffff047820350400000000040053acab14f3e603000000000652635100ab630ce66c03000000000001bdc704000000000765650065ac51ac3e886381", "51", 0, -263340864, "ed5622ac642d11f90e68c0feea6a2fe36d880ecae6b8c0d89c4ea4b3d162bd90"],
+	["cfa147d2017fe84122122b4dda2f0d6318e59e60a7207a2d00737b5d89694d480a2c26324b0000000006006351526552ffffffff0456b5b804000000000800516aab525363ab166633000000000004655363ab254c0e02000000000952ab6a6a00ab525151097c1b020000000009656a52ac6300530065ad0d6e50", "6a535165ac6a536500", 0, -574683184, "f926d4036eac7f019a2b0b65356c4ee2fe50e089dd7a70f1843a9f7bc6997b35"],
+	["91c5d5f6022fea6f230cc4ae446ce040d8313071c5ac1749c82982cc1988c94cb1738aa48503000000016a19e204f30cb45dd29e68ff4ae160da037e5fc93538e21a11b92d9dd51cf0b5efacba4dd70000000005656a6aac51ffffffff03db126905000000000953006a53ab6563636a36a273030000000006656a52656552b03ede00000000000352516500000000", "530052526a00", 1, 1437328441, "255c125b60ee85f4718b2972174c83588ee214958c3627f51f13b5fb56c8c317"],
+	["03f20dc202c886907b607e278731ebc5d7373c348c8c66cac167560f19b341b782dfb634cb03000000076a51ac6aab63abea3e8de7adb9f599c9caba95aa3fa852e947fc88ed97ee50e0a0ec0d14d164f44c0115c10100000004ab5153516fdd679e0414edbd000000000005ac636a53512021f2040000000007006a0051536a52c73db2050000000005525265ac5369046e000000000003ab006a1ef7bd1e", "52656a", 0, 1360223035, "5a0a05e32ce4cd0558aabd5d79cd5fcbffa95c07137506e875a9afcba4bef5a2"],
+	["d9611140036881b61e01627078512bc3378386e1d4761f959d480fdb9d9710bebddba2079d020000000763536aab5153ab819271b41e228f5b04daa1d4e72c8e1955230accd790640b81783cfc165116a9f535a74c000000000163ffffffffa2e7bb9a28e810624c251ff5ba6b0f07a356ac082048cf9f39ec036bba3d431a02000000076a000000ac65acffffffff01678a820000000000085363515153ac635100000000", "535353", 2, -82213851, "52b9e0778206af68998cbc4ebdaad5a9469e04d0a0a6cef251abfdbb74e2f031"],
+	["98b3a0bf034233afdcf0df9d46ac65be84ef839e58ee9fa59f32daaa7d684b6bdac30081c60200000007636351acabababffffffffc71cf82ded4d1593e5825618dc1d5752ae30560ecfaa07f192731d68ea768d0f0100000006650052636563f3a2888deb5ddd161430177ce298242c1a86844619bc60ca2590d98243b5385bc52a5b8f00000000095365acacab520052ac50d4722801c3b8a60300000000035165517e563b65", "51", 1, -168940690, "b6b684e2d2ecec8a8dce4ed3fc1147f8b2e45732444222aa8f52d860c2a27a9d"],
+	["97be4f7702dc20b087a1fdd533c7de762a3f2867a8f439bddf0dcec9a374dfd0276f9c55cc0300000000cdfb1dbe6582499569127bda6ca4aaff02c132dc73e15dcd91d73da77e92a32a13d1a0ba0200000002ab51ffffffff048cfbe202000000000900516351515363ac535128ce0100000000076aac5365ab6aabc84e8302000000000863536a53ab6a6552f051230500000000066aac535153510848d813", "ac51", 0, 229541474, "e5da9a416ea883be1f8b8b2d178463633f19de3fa82ae25d44ffb531e35bdbc8"],
+	["085b6e04040b5bff81e29b646f0ed4a45e05890a8d32780c49d09643e69cdccb5bd81357670100000001abffffffffa5c981fe758307648e783217e3b4349e31a557602225e237f62b636ec26df1a80300000004650052ab4792e1da2930cc90822a8d2a0a91ea343317bce5356b6aa8aae6c3956076aa33a5351a9c0300000004abac5265e27ddbcd472a2f13325cc6be40049d53f3e266ac082172f17f6df817db1936d9ff48c02b000000000152ffffffff021aa7670500000000085353635163ab51ac14d584000000000001aca4d136cc", "6a525300536352536a", 0, -1398925877, "41ecca1e8152ec55074f4c39f8f2a7204dda48e9ec1e7f99d5e7e4044d159d43"],
+	["eec32fff03c6a18b12cd7b60b7bdc2dd74a08977e53fdd756000af221228fe736bd9c42d870100000007005353ac515265ffffffff037929791a188e9980e8b9cc154ad1b0d05fb322932501698195ab5b219488fc02000000070063510065ab6a0bfc176aa7e84f771ea3d45a6b9c24887ceea715a0ff10ede63db8f089e97d927075b4f1000000000551abab63abffffffff02eb933c000000000000262c420000000000036563632549c2b6", "6352", 2, 1480445874, "ff8a4016dfdd918f53a45d3a1f62b12c407cd147d68ca5c92b7520e12c353ff5"],
+	["98ea7eac0313d9fb03573fb2b8e718180c70ce647bebcf49b97a8403837a2556cb8c9377f30000000004ac53ac65ffffffff8caac77a5e52f0d8213ef6ce998bedbb50cfdf108954771031c0e0cd2a78423900000000010066e99a44937ebb37015be3693761078ad5c73aa73ec623ac7300b45375cc8eef36087eb80000000007515352acac5100ffffffff0114a51b02000000000000000000", "6aacab", 0, 243527074, "bad77967f98941af4dd52a8517d5ad1e32307c0d511e15461e86465e1b8b5273"],
+	["3ab70f4604e8fc7f9de395ec3e4c3de0d560212e84a63f8d75333b604237aa52a10da17196000000000763526a6553ac63a25de6fd66563d71471716fe59087be0dde98e969e2b359282cf11f82f14b00f1c0ac70f02000000050052516aacdffed6bb6889a13e46956f4b8af20752f10185838fd4654e3191bf49579c961f5597c36c0100000005ac636363abc3a1785bae5b8a1b4be5d0cbfadc240b4f7acaa7dfed6a66e852835df5eb9ac3c553766801000000036a65630733b7530218569602000000000952006a6a6a51acab52777f06030000000007ac0063530052abc08267c9", "000000536aac0000", 1, 1919096509, "df1c87cf3ba70e754d19618a39fdbd2970def0c1bfc4576260cba5f025b87532"],
+	["bdb6b4d704af0b7234ced671c04ba57421aba7ead0a117d925d7ebd6ca078ec6e7b93eea6600000000026565ffffffff3270f5ad8f46495d69b9d71d4ab0238cbf86cc4908927fbb70a71fa3043108e6010000000700516a65655152ffffffff6085a0fdc03ae8567d0562c584e8bfe13a1bd1094c518690ebcb2b7c6ce5f04502000000095251530052536a53aba576a37f2c516aad9911f687fe83d0ae7983686b6269b4dd54701cb5ce9ec91f0e6828390300000000ffffffff04cc76cc020000000002656a01ffb702000000000253ab534610040000000009acab006565516a00521f55f5040000000000389dfee9", "6a525165", 0, 1336204763, "71c294523c48fd7747eebefbf3ca06e25db7b36bff6d95b41c522fecb264a919"],
+	["54258edd017d22b274fbf0317555aaf11318affef5a5f0ae45a43d9ca4aa652c6e85f8a040010000000953ac65ab5251656500ffffffff03321d450000000000085265526a51526a529ede8b030000000003635151ce6065020000000001534c56ec1b", "acac", 0, 2094130012, "110d90fea9470dfe6c5048f45c3af5e8cc0cb77dd58fd13d338268e1c24b1ccc"],
+	["ce0d322e04f0ffc7774218b251530a7b64ebefca55c90db3d0624c0ff4b3f03f918e8cf6f60300000003656500ffffffff9cce943872da8d8af29022d0b6321af5fefc004a281d07b598b95f6dcc07b1830200000007abab515351acab8d926410e69d76b7e584aad1470a97b14b9c879c8b43f9a9238e52a2c2fefc2001c56af8010000000400ab5253cd2cd1fe192ce3a93b5478af82fa250c27064df82ba416dfb0debf4f0eb307a746b6928901000000096500abacac6a0063514214524502947efc0200000000035251652c40340100000000096a6aab52000052656a5231c54c", "51", 2, -2090320538, "0322ca570446869ec7ec6ad66d9838cff95405002d474c0d3c17708c7ee039c6"],
+	["47ac54940313430712ebb32004679d3a512242c2b33d549bf5bbc8420ec1fd0850ed50eb6d0300000009536aac6a65acacab51ffffffffb843e44266ce2462f92e6bff54316661048c8c17ecb092cb493b39bfca9117850000000001519ab348c05e74ebc3f67423724a3371dd99e3bceb4f098f8860148f48ad70000313c4c223000000000653006565656512c2d8dc033f3c97010000000002636aa993aa010000000006526365ab526ab7cf560300000000076a0065ac6a526500000000", "005352535300ab6a", 2, 59531991, "8b5b3d00d9c658f062fe6c5298e54b1fe4ed3a3eab2a87af4f3119edc47b1691"],
+	["233cd90b043916fc41eb870c64543f0111fb31f3c486dc72457689dea58f75c16ae59e9eb2000000000500536a6a6affffffff9ae30de76be7cd57fb81220fce78d74a13b2dbcad4d023f3cadb3c9a0e45a3ce000000000965ac6353ac5165515130834512dfb293f87cb1879d8d1b20ebad9d7d3d5c3e399a291ce86a3b4d30e4e32368a9020000000453005165ffffffff26d84ae93eb58c81158c9b3c3cbc24a84614d731094f38d0eea8686dec02824d0300000005636a65abacf02c784001a0bd5d03000000000900655351ab65ac516a416ef503", "", 1, -295106477, "b79f31c289e95d9dadec48ebf88e27c1d920661e50d090e422957f90ff94cb6e"],
+	["9200e26b03ff36bc4bf908143de5f97d4d02358db642bd5a8541e6ff709c420d1482d471b70000000008abab65536a636553ffffffff61ba6d15f5453b5079fb494af4c48de713a0c3e7f6454d7450074a2a80cb6d880300000007ac6a00ab5165515dfb7574fbce822892c2acb5d978188b1d65f969e4fe874b08db4c791d176113272a5cc10100000000ffffffff0420958d000000000009ac63516a0063516353dd885505000000000465ac00007b79e901000000000066d8bf010000000005525252006a00000000", "ac5152", 0, 2089531339, "89ec7fab7cfe7d8d7d96956613c49dc48bf295269cfb4ea44f7333d88c170e62"],
+	["45f335ba01ce2073a8b0273884eb5b48f56df474fc3dff310d9706a8ac7202cf5ac188272103000000025363ffffffff049d859502000000000365ab6a8e98b1030000000002ac51f3a80603000000000752535151ac00000306e30300000000020051b58b2b3a", "", 0, 1899564574, "78e01310a228f645c23a2ad0acbb8d91cedff4ecdf7ca997662c6031eb702b11"],
+	["d8f652a6043b4faeada05e14b81756cd6920cfcf332e97f4086961d49232ad6ffb6bc6c097000000000453526563ffffffff1ea4d60e5e91193fbbc1a476c8785a79a4c11ec5e5d6c9950c668ceacfe07a15020000000352ab51fffffffffe029a374595c4edd382875a8dd3f20b9820abb3e93f877b622598d11d0b09e503000000095351000052ac515152ffffffff9d65fea491b979699ceb13caf2479cd42a354bd674ded3925e760758e85a756803000000046365acabffffffff0169001d00000000000651636a65656300000000", "ab0063630000ac", 3, 1050965951, "4cc85cbc2863ee7dbce15490d8ca2c5ded61998257b9eeaff968fe38e9f009ae"],
+	["718662be026e1dcf672869ac658fd0c87d6835cfbb34bd854c44e577d5708a7faecda96e260300000004526a636a489493073353b678549adc7640281b9cbcb225037f84007c57e55b874366bb7b0fa03bdc00000000095165ababac65ac00008ab7f2a802eaa53d000000000007acac516aac526ae92f380100000000056aac00536500000000", "ab00", 1, 43296088, "2d642ceee910abff0af2116af75b2e117ffb7469b2f19ad8fef08f558416d8f7"],
+	["94083c840288d40a6983faca876d452f7c52a07de9268ad892e70a81e150d602a773c175ad03000000007ec3637d7e1103e2e7e0c61896cbbf8d7e205b2ecc93dd0d6d7527d39cdbf6d335789f660300000000ffffffff019e1f7b03000000000800ac0051acac0053539cb363", "", 1, -183614058, "a17b66d6bb427f42653d08207a22b02353dd19ccf2c7de6a9a3a2bdb7c49c9e7"],
+	["30e0d4d20493d0cd0e640b757c9c47a823120e012b3b64c9c1890f9a087ae4f2001ca22a61010000000152f8f05468303b8fcfaad1fb60534a08fe90daa79bff51675472528ebe1438b6f60e7f60c10100000009526aab6551ac510053ffffffffaaab73957ea2133e32329795221ed44548a0d3a54d1cf9c96827e7cffd1706df0200000009ab00526a005265526affffffffd19a6fe54352015bf170119742821696f64083b5f14fb5c7d1b5a721a3d7786801000000085265abababac53abffffffff020f39bd030000000004ab6aac52049f6c050000000004ab52516aba5b4c60", "6a6365516a6a655253", 0, -624256405, "8e221a6c4bf81ca0d8a0464562674dcd14a76a32a4b7baf99450dd9195d411e6"],
+	["f9c69d940276ec00f65f9fe08120fc89385d7350388508fd80f4a6ba2b5d4597a9e21c884f010000000663ab63ababab15473ae6d82c744c07fc876ecd53bd0f3018b2dbedad77d757d5bdf3811b23d294e8c0170000000001abafababe00157ede2050000000006ac6a5263635300000000", "ab53", 1, 606547088, "714d8b14699835b26b2f94c58b6ea4c53da3f7adf0c62ea9966b1e1758272c47"],
+	["5c0ac112032d6885b7a9071d3c5f493aa16c610a4a57228b2491258c38de8302014276e8be030000000300ab6a17468315215262ad5c7393bb5e0c5a6429fd1911f78f6f72dafbbbb78f3149a5073e24740300000003ac5100ffffffff33c7a14a062bdea1be3c9c8e973f54ade53fe4a69dcb5ab019df5f3345050be00100000008ac63655163526aab428defc0033ec36203000000000765516365536a00ae55b2000000000002ab53f4c0080400000000095265516a536563536a00000000", "6a005151006a", 2, 272749594, "91082410630337a5d89ff19145097090f25d4a20bdd657b4b953927b2f62c73b"],
+	["e3683329026720010b08d4bec0faa244f159ae10aa582252dd0f3f80046a4e145207d54d31000000000852acac52656aacac3aaf2a5017438ad6adfa3f9d05f53ebed9ceb1b10d809d507bcf75e0604254a8259fc29c020000000653526552ab51f926e52c04b44918030000000000f7679c0100000000090000525152005365539e3f48050000000009516500ab635363ab008396c905000000000253650591024f", "6a6365", 0, 908746924, "458aec3b5089a585b6bad9f99fd37a2b443dc5a2eefac2b7e8c5b06705efc9db"],
+	["48c4afb204204209e1df6805f0697edaa42c0450bbbd767941fe125b9bc40614d63d757e2203000000066a5363005152dc8b6a605a6d1088e631af3c94b8164e36e61445e2c60130292d81dabd30d15f54b355a802000000036a6353ffffffff1d05dcec4f3dedcfd02c042ce5d230587ee92cb22b52b1e59863f3717df2362f0300000005536552ac52ffffffffd4d71c4f0a7d53ba47bb0289ca79b1e33d4c569c1e951dd611fc9c9c1ca8bc6c030000000865536a65ab51abacffffffff042f9aa905000000000753655153656351ab93d8010000000002655337440e0300000000005d4c690000000000015278587acb", "ab006565526a51", 0, 1502064227, "bbed77ff0f808aa8abd946ba9e7ec1ddb003a969fa223dee0af779643cb841a9"],
+	["00b20fd104dd59705b84d67441019fa26c4c3dec5fd3b50eca1aa549e750ef9ddb774dcabe000000000651ac656aac65ffffffff52d4246f2db568fc9eea143e4d260c698a319f0d0670f84c9c83341204fde48b0200000000ffffffffb8aeabb85d3bcbc67b132f1fd815b451ea12dcf7fc169c1bc2e2cf433eb6777a03000000086a51ac6aab6563acd510d209f413da2cf036a31b0def1e4dcd8115abf2e511afbcccb5ddf41d9702f28c52900100000006ac52ab6a0065ffffffff039c8276000000000008ab53655200656a52401561010000000003acab0082b7160100000000035100ab00000000", "535265", 1, -947367579, "3212c6d6dd8d9d3b2ac959dec11f4638ccde9be6ed5d36955769294e23343da0"],
+	["455131860220abbaa72015519090a666faf137a0febce7edd49da1eada41feab1505a0028b02000000036365ab453ead4225724eb69beb590f2ec56a7693a608871e0ab0c34f5e96157f90e0a96148f3c502000000085251ab51535163acffffffff022d1249040000000009abac00acac6565630088b310040000000000e3920e59", "5152ab6a52ac5152", 0, 294375737, "c40fd7dfa72321ac79516502500478d09a35cc22cc264d652c7d18b14400b739"],
+	["624d28cb02c8747915e9af2b13c79b417eb34d2fa2a73547897770ace08c6dd9de528848d3030000000651ab63abab533c69d3f9b75b6ef8ed2df50c2210fd0bf4e889c42477d58682f711cbaece1a626194bb85030000000765acab53ac5353ffffffff018cc280040000000009abacabac52636352ac6859409e", "ac51ac", 1, 1005144875, "919144aada50db8675b7f9a6849c9d263b86450570293a03c245bd1e3095e292"],
+	["8f28471d02f7d41b2e70e9b4c804f2d90d23fb24d53426fa746bcdcfffea864925bdeabe3e0200000001acffffffff76d1d35d04db0e64d65810c808fe40168f8d1f2143902a1cc551034fd193be0e0000000001acffffffff048a5565000000000005005151516afafb610400000000045263ac53648bb30500000000086363516a6a5165513245de01000000000000000000", "6a0053510053", 1, -1525137460, "305fc8ff5dc04ebd9b6448b03c9a3d945a11567206c8d5214666b30ec6d0d6cc"],
+	["10ec50d7046b8b40e4222a3c6449490ebe41513aad2eca7848284a08f3069f3352c2a9954f0000000009526aac656352acac53ffffffff0d979f236155aa972472d43ee6f8ce22a2d052c740f10b59211454ff22cb7fd00200000007acacacab63ab53ffffffffbbf97ebde8969b35725b2e240092a986a2cbfd58de48c4475fe077bdd493a20c010000000663ab5365ababffffffff4600722d33b8dba300d3ad037bcfc6038b1db8abfe8008a15a1de2da2264007302000000035351ac6dbdafaf020d0ccf04000000000663ab6a51ab6ae06e5e0200000000036aabab00000000", "", 0, -1658960232, "2420dd722e229eccafae8508e7b8d75c6920bfdb3b5bac7cb8e23419480637c2"],
+	["fef98b7101bf99277b08a6eff17d08f3fcb862e20e13138a77d66fba55d54f26304143e5360100000006515365abab00ffffffff04265965030000000004655252ace2c775010000000001002b23b4040000000007516a5153ab53ac456a7a00000000000753ab525251acacba521291", "526aacacab00abab53", 0, -1614097109, "4370d05c07e231d6515c7e454a4e401000b99329d22ed7def323976fa1d2eeb5"],
+	["34a2b8830253661b373b519546552a2c3bff7414ea0060df183b1052683d78d8f54e842442000000000152ffffffffd961a8e34cf374151058dfcddc86509b33832bc57267c63489f69ff01199697c0300000002abacba856cfb01b17c2f050000000008515365ac53ab000000000000", "5263ab656a", 1, -2104480987, "2f9993e0a84a6ca560d6d1cc2b63ffe7fd71236d9cfe7d809491cef62bbfad84"],
+	["43559290038f32fda86580dd8a4bc4422db88dd22a626b8bd4f10f1c9dd325c8dc49bf479f01000000026351ffffffff401339530e1ed3ffe996578a17c3ec9d6fccb0723dd63e7b3f39e2c44b976b7b0300000006ab6a65656a51ffffffff6fb9ba041c96b886482009f56c09c22e7b0d33091f2ac5418d05708951816ce7000000000551ac525100ffffffff020921e40500000000035365533986f40500000000016a00000000", "52ac51", 0, 1769771809, "02040283ef2291d8e1f79bb71bdabe7c1546c40d7ed615c375643000a8b9600d"],
+	["6878a6bd02e7e1c8082d5e3ee1b746cfebfac9e8b97e61caa9e0759d8a8ecb3743e36a30de0100000002ab532a911b0f12b73e0071f5d50b6bdaf783f4b9a6ce90ec0cad9eecca27d5abae188241ddec0200000001651c7758d803f7457b0500000000036551515f4e90000000000001007022080200000000035365acc86b6946", "6351ab", 0, -1929374995, "f24be499c58295f3a07f5f1c6e5084496ae160450bd61fdb2934e615289448f1"],
+	["35b6fc06047ebad04783a5167ab5fc9878a00c4eb5e7d70ef297c33d5abd5137a2dea9912402000000036aacacffffffff21dc291763419a584bdb3ed4f6f8c60b218aaa5b99784e4ba8acfec04993e50c03000000046a00ac6affffffff69e04d77e4b662a82db71a68dd72ef0af48ca5bebdcb40f5edf0caf591bb41020200000000b5db78a16d93f5f24d7d932f93a29bb4b784febd0cbb1943f90216dc80bba15a0567684b000000000853ab52ab5100006a1be2208a02f6bdc103000000000265ab8550ea04000000000365636a00000000", "", 0, -1114114836, "1c8655969b241e717b841526f87e6bd68b2329905ba3fc9e9f72526c0b3ea20c"],
+	["bebb90c302bf91fd4501d33555a5fc5f2e1be281d9b7743680979b65c3c919108cc2f517510100000003abab00ffffffff969c30053f1276550532d0aa33cfe80ca63758cd215b740448a9c08a84826f3303000000056565ab5153ffffffff04bf6f2a04000000000565ab5265ab903e760100000000026a6a7103fa020000000006526553525365b05b2c000000000006ab000000535300000000", "51510053ab63635153", 1, 1081291172, "94338cd47a4639be30a71e21a7103cee4c99ef7297e0edd56aaf57a068b004de"],
+	["af48319f031b4eeb4319714a285f44244f283cbff30dcb9275b06f2348ccd0d7f015b54f8500000000066363ac65ac6affffffff2560a9817ebbc738ad01d0c9b9cf657b8f9179b1a7f073eb0b67517409d108180200000005ac6365ab52ffffffff0bdd67cd4ecae96249a2e2a96db1490ee645f042fd9d5579de945e22b799f4d003000000086552ab515153ab00cf187c8202e51abf0300000000066552006a00abadf37d000000000004ac6a535100000000", "63ab65", 1, -1855554446, "60caf46a7625f303c04706cec515a44b68ec319ee92273acb566cca4f66861c1"],
+	["f35befbc03faf8c25cc4bc0b92f6239f477e663b44b83065c9cb7cf231243032cf367ce3130000000005ab65526a517c4c334149a9c9edc39e29276a4b3ffbbab337de7908ea6f88af331228bd90086a6900ba020000000151279d19950d2fe81979b72ce3a33c6d82ebb92f9a2e164b6471ac857f3bbd3c0ea213b542010000000953ab51635363520065052657c20300a9ba04000000000452636a6a0516ea020000000008535253656365ababcfdd3f01000000000865ac516aac00530000000000", "", 2, -99793521, "c834a5485e68dc13edb6c79948784712122440d7fa5bbaa5cd2fc3d4dac8185d"],
+	["d3da18520216601acf885414538ce2fb4d910997eeb91582cac42eb6982c9381589587794f0300000000fffffffff1b1c9880356852e10cf41c02e928748dd8fae2e988be4e1c4cb32d0bfaea6f7000000000465ab6aabffffffff02fb0d69050000000002ababeda8580500000000085163526565ac52522b913c95", "ac", 1, -1247973017, "99b32b5679d91e0f9cdd6737afeb07459806e5acd7630c6a3b9ab5d550d0c003"],
+	["8218eb740229c695c252e3630fc6257c42624f974bc856b7af8208df643a6c520ef681bfd00000000002510066f30f270a09b2b420e274c14d07430008e7886ec621ba45665057120afce58befca96010300000004525153ab84c380a9015d96100000000000076a5300acac526500000000", "ac005263", 0, -1855679695, "5071f8acf96aea41c7518bd1b5b6bbe16258b529df0c03f9e374b83c66b742c6"],
+	["1123e7010240310013c74e5def60d8e14dd67aedff5a57d07a24abc84d933483431b8cf8ea0300000003530051fc6775ff1a23c627a2e605dd2560e84e27f4208300071e90f4589e762ad9c9fe8d0da95e020000000465655200ffffffff04251598030000000004ab65ab639d28d90400000000096563636aacac525153474df801000000000851525165ac51006a75e23b040000000000e5bd3a4a", "6363636565", 0, -467124448, "9cb0dd04e9fe287b112e94a1647590d27e8b164ca13c4fe70c610fd13f82c2fd"],
+	["fd92fe1003083c5179f97e77bf7d71975788138147adbdb283306802e261c0aee080fa22630200000000860c643ba9a1816b9badf36077b4554d11720e284e395a1121bc45279e148b2064c65e49020000000651ab6a53636a2c713088d20f4bc4001264d972cce05b9fe004dc33376ad24d0d013e417b91a5f1b6734e000000000100ffffffff02e3064c0500000000066552006a5165b86e8705000000000665ab65ab53522052eadb", "00ab53525265", 0, 776203277, "47207b48777727532f62e09afcd4104ea6687e723c7657c30504fa2081331cc8"],
+	["d1b6a703038f14d41fcc5cc45455faa135a5322be4bf0f5cbcd526578fc270a236cacb853f0200000001abffffffff135aeff902fa38f202ccf5bd34437ff89c9dc57a028b62447a0a38579383e8ef0000000000ffffffffadf398d2c818d0b90bc474f540c3618a4a643482eeab73d36101987e2ec0335900000000004bd3323504e69fc10000000000055151535251790ada02000000000563ab6aab521337a704000000000963ac63abacac52656a1e9862010000000007656500ac51ab6a8f4ee672", "ab5251656565ac63", 2, 82008394, "b8f3d255549909c07588ecba10a02e55a2d6f2206d831af9da1a7dae64cfbc8b"],
+	["81dadaa7011556683db3fe95262f4fdb20391b7e75b7ffcee51b176af64d83c06f85545d620200000005ab5151ab52ffffffff044805ef0300000000065353516352639702c802000000000900516351515252ab5270db08040000000009ac516aab526553abac4aabc90500000000096365ab0052636a525100000000", "6565ab6a5152", 0, -2126294159, "ad01ec9d6dbae325ec3a8e1fd98e2d03b1188378210efef093dd8b0b0ef3f19d"],
+	["3b937e05032b8895d2f4945cb7e3679be2fbd15311e2414f4184706dbfc0558cf7de7b4d000000000001638b91a12668a3c3ce349788c961c26aa893c862f1e630f18d80e7843686b6e1e6fc396310000000000852635353ab65ac51eeb09dd1c9605391258ee6f74b9ae17b5e8c2ef010dc721c5433dcdc6e93a1593e3b6d1700000000085365ac6553526351ffffffff0308b18e04000000000253acb6dd00040000000008536aac5153ac516ab0a88201000000000500ac006500804e3ff2", "", 0, 416167343, "595a3c02254564634e8085283ec4ea7c23808da97ce9c5da7aecd7b553e7fd7f"],
+	["a48f27ca047997470da74c8ee086ddad82f36d9c22e790bd6f8603ee6e27ad4d3174ea875403000000095153ac636aab6aacabffffffffefc936294e468d2c9a99e09909ba599978a8c0891ad47dc00ba424761627cef202000000056a51630053ffffffff304cae7ed2d3dbb4f2fbd679da442aed06221ffda9aee460a28ceec5a9399f4e0200000000f5bddf82c9c25fc29c5729274c1ff0b43934303e5f595ce86316fc66ad263b96ca46ab8d0100000003536500d7cf226b0146b00c04000000000200ac5c2014ce", "515100636563", 0, 1991799059, "9c051a7092fe17fa62b1720bc2c4cb2ffc1527d9fb0b006d2e142bb8fe07bf3c"],
+	["180cd53101c5074cf0b7f089d139e837fe49932791f73fa2342bd823c6df6a2f72fe6dba1303000000076a6a63ac53acabffffffff03853bc1020000000007ac526a6a6a6a003c4a8903000000000453515163a0fbbd030000000005ab656a5253253d64cf", "ac65", 0, -1548453970, "4d8efb3b99b9064d2f6be33b194a903ffabb9d0e7baa97a48fcec038072aac06"],
+	["c21ec8b60376c47e057f2c71caa90269888d0ffd5c46a471649144a920d0b409e56f190b700000000008acac6a526a536365ffffffff5d315d9da8bf643a9ba11299450b1f87272e6030fdb0c8adc04e6c1bfc87de9a0000000000ea43a9a142e5830c96b0ce827663af36b23b0277244658f8f606e95384574b91750b8e940000000007516a63ac0063acffffffff023c61be0400000000055165ab5263313cc8020000000006006a53526551ed8c3d56", "6a", 1, 1160627414, "a638cc17fd91f4b1e77877e8d82448c84b2a4e100df1373f779de7ad32695112"],
+	["128cd90f04b66a4cbc78bf48748f6eec0f08d5193ee8d0a6f2e8d3e5f138ed12c2c87d01a301000000085200ab6aac00ab00ffffffff09fc88bb1851e3dfb3d30179c38e15aeb1b39929c7c74f6acd071994ed4806490300000000e7fc5ea12ec56f56c0d758ecf4bb88aa95f3b08176b336db3b9bec2f6e27336dce28adbe030000000400530051fffffffffd6ff1adcf1fbe0d883451ee46904f1b7e8820243d395559b2d4ee8190a6e891000000000080fb1ae702f85b400000000000035200ab8d9651010000000006ab6a52536aab00000000", "ab", 1, 1667598199, "c10ccc9db8a92d7d4b133a2980782dab9d9d1d633d0dde9f9612ada57771fd89"],
+	["da9695a403493d3511c10e1fe1286f954db0366b7667c91ef18ae4578056c1bf752114ac5901000000035351519788d91dd1f9c62dc005d80ea54eb13f7131ca5aace3d5d29f9b58ccc5fbc9a27e779950010000000453ac6a00ffffffffe2556ff29ebe83eb42a32c7a8d93bc598043578f491b5935805a33608538845a030000000252ab65d21b3b018f26c4030000000006acab51535352e1cbcb10", "006565ab52", 2, -1550927794, "0ca673a1ee66f9625ceb9ab278ebef772c113c188112b02824570c17fdf48194"],
+	["b240517501334021240427adb0b413433641555424f6d24647211e3e6bfbb22a8045cbda2f000000000071bac8630112717802000000000000000000", "6a5165abac52656551", 0, 1790414254, "2c8be597620d95abd88f9c1cf4967c1ae3ca2309f3afec8928058c9598660e9e"],
+	["96bac43903044a199b4b3efeeec5d196ee23fb05495541fa2cd6fb6405a9432d1723363660010000000151ffffffffe6ce2b66ce1488918a3e880bebb0e750123f007c7bcbac8fcd67ce75cb6fbae80300000000ffffffff9c0955aa07f506455834895c0c56be5a095398f47c62a3d431fe125b161d666a0200000005520000abac7ffdbc540216f2f004000000000165a26dce010000000001ab00000000", "5151ab656a656a6a63", 0, -707123065, "26b22e18d5d9081fde9631594a4f7c49069ed2e429f3d08caf9d834f685ccab2"],
+	["b8fd394001ed255f49ad491fecc990b7f38688e9c837ccbc7714ddbbf5404f42524e68c18f0000000007ab6353535363ab081e15ee02706f7d050000000008515200535351526364c7ec040000000005636a53acac9206cbe1", "655352ac", 0, -1251578838, "8e0697d8cd8a9ccea837fd798cc6c5ed29f6fbd1892ee9bcb6c944772778af19"],
+	["e42a76740264677829e30ed610864160c7f97232c16528fe5610fc08814b21c34eefcea69d010000000653006a6a0052ffffffff647046cf44f217d040e6a8ff3f295312ab4dd5a0df231c66968ad1c6d8f4428000000000025352ffffffff0199a7f900000000000000000000", "655263006a005163", 1, 1122505713, "7cda43f1ff9191c646c56a4e29b1a8c6cb3f7b331da6883ef2f0480a515d0861"],
+	["0f034f32027a8e094119443aa9cfe11737c6d7dda9a52b839bc073dcc0235b847b28e0fab60200000006ac53ac536a63eee63447dfdad80476994b68706e916df1bd9d7cb4f3a4f6b14369de84564bea2e8688bd030000000565636a65acf8434663020b35fe01000000000800abab655163acabb3d6a103000000000353acab345eeda0", "526a51ac63ab51", 1, 66020215, "4435e62ff6531ac73529aac9cf878a7219e0b6e6cac79af8487c5355d1ad6d43"],
+	["a2dfa4690214c1ab25331815a5128f143219de51a47abdc7ce2d367e683eeb93960a31af9f010000000363636affffffff8be0628abb1861b078fcc19c236bc4cc726fa49068b88ad170adb2a97862e7460200000004ac655363ffffffff0441f11103000000000153dbab0c000000000009ab53ac5365526aab63abbb95050000000004ab52516a29a029040000000003ac526a00000000", "6a52ac63", 1, -1302210567, "913060c7454e6c80f5ba3835454b54db2188e37dc4ce72a16b37d11a430b3d23"],
+	["9dbc591f04521670af83fb3bb591c5d4da99206f5d38e020289f7db95414390dddbbeb56680100000004ac5100acffffffffb6a40b5e29d5e459f8e72d39f800089529f0889006cad3d734011991da8ef09d0100000009526a5100acab536a515fc427436df97cc51dc8497642ffc868857ee245314d28b356bd70adba671bd6071301fc0000000000ffffffff487efde2f620566a9b017b2e6e6d42525e4070f73a602f85c6dfd58304518db30000000005516353006a8d8090180244904a0200000000046a65656ab1e9c203000000000451ab63aba06a5449", "", 0, -1414953913, "bae189eb3d64aedbc28a6c28f6c0ccbd58472caaf0cf45a5aabae3e031dd1fea"],
+	["1345fb2c04bb21a35ae33a3f9f295bece34650308a9d8984a989dfe4c977790b0c21ff9a7f0000000006ac52ac6a0053ffffffff7baee9e8717d81d375a43b691e91579be53875350dfe23ba0058ea950029fcb7020000000753ab53ab63ab52ffffffff684b6b3828dfb4c8a92043b49b8cb15dd3a7c98b978da1d314dce5b9570dadd202000000086353ab6a5200ac63d1a8647bf667ceb2eae7ec75569ca249fbfd5d1b582acfbd7e1fcf5886121fca699c011d0100000003ac006affffffff049b1eb00300000000001e46dc0100000000080065ab6a6a630065ca95b40300000000030051520c8499010000000006ab6aac526a6500000000", "53526aac636300", 2, 1809978100, "cfeaa36790bc398783d4ca45e6354e1ea52ee74e005df7f9ebd10a680e9607bf"],
+	["7d75dc8f011e5f9f7313ba6aedef8dbe10d0a471aca88bbfc0c4a448ce424a2c5580cda1560300000003ab5152ffffffff01997f8e0200000000096552ac6a65656563530d93bbcc", "00656a6563", 0, 1414485913, "ec91eda1149f75bffb97612569a78855498c5d5386d473752a2c81454f297fa7"],
+	["1459179504b69f01c066e8ade5e124c748ae5652566b34ed673eea38568c483a5a4c4836ca0100000008ac5352006563656affffffff5d4e037880ab1975ce95ea378d2874dcd49d5e01e1cdbfae3343a01f383fa35800000000095251ac52ac6aac6500ffffffff7de3ae7d97373b7f2aeb4c55137b5e947b2d5fb325e892530cb589bc4f92abd503000000086563ac53ab520052ffffffffb4db36a32d6e543ef49f4bafde46053cb85b2a6c4f0e19fa0860d9083901a1190300000003ab51531bbcfe5504a6dbda040000000008536a5365abac6500d660c80300000000096565abab6a53536a6a54e84e010000000003acac52df2ccf0500000000025351220c857e", "", 2, 1879181631, "3aad18a209fab8db44954eb55fd3cc7689b5ec9c77373a4d5f4dae8f7ae58d14"],
+	["d98b777f04b1b3f4de16b07a05c31d79965579d0edda05600c118908d7cf642c9cd670093f020000000953005351ac65ab5363a268caad6733b7d1718008997f249e1375eb3ab9fe68ab0fe170d8e745ea24f54ce67f9b00000000066500516a5151ffffffff7ef8040dfcc86a0651f5907e8bfd1017c940f51cf8d57e3d3fe78d57e40b1e610200000003535263ffffffff39846cfed4babc098ff465256ba3820c30d710581316afcb67cd31c623b703360300000001acffffffff03d405120100000000056300006a5201a73d050000000004ab636a6a294c8c000000000006ac65536553ac00000000", "63525351abac", 1, 2018694761, "86970af23c89b72a4f9d6281e46b9ef5220816bed71ebf1ae20df53f38fe16ff"],
+	["cabb1b06045a895e6dcfc0c1e971e94130c46feace286759f69a16d298c8b0f6fd0afef8f20300000004ac006352ffffffffa299f5edac903072bfb7d29b663c1dd1345c2a33546a508ba5cf17aab911234602000000056a65515365ffffffff89a20dc2ee0524b361231092a070ace03343b162e7162479c96b757739c8394a0300000002abab92ec524daf73fabee63f95c1b79fa8b84e92d0e8bac57295e1d0adc55dc7af5534ebea410200000001534d70e79b04674f6f00000000000600abacab53517d60cc0200000000035265ab96c51d040000000004ac6300ac62a787050000000008006a516563ab63639e2e7ff7", "6551ac6351ac", 3, 1942663262, "d0c4a780e4e0bc22e2f231e23f01c9d536b09f6e5be51c123d218e906ec518be"],
+	["8b96d7a30132f6005b5bd33ea82aa325e2bcb441f46f63b5fca159ac7094499f380f6b7e2e00000000076aacabac6300acffffffff0158056700000000000465005100c319e6d0", "52006a", 0, -1100733473, "fb4bd26a91b5cf225dd3f170eb09bad0eac314bc1e74503cc2a3f376833f183e"],
+	["112191b7013cfbe18a175eaf09af7a43cbac2c396f3695bbe050e1e5f4250603056d60910e02000000001c8a5bba03738a22010000000005525352656a77a149010000000002510003b52302000000000351ac52722be8e6", "65ac6565", 0, -1847972737, "8e795aeef18f510d117dfa2b9f4a2bd2e2847a343205276cedd2ba14548fd63f"],
+	["ce6e1a9e04b4c746318424705ea69517e5e0343357d131ad55d071562d0b6ebfedafd6cb840100000003656553ffffffff67bd2fa78e2f52d9f8900c58b84c27ef9d7679f67a0a6f78645ce61b883fb8de000000000100d699a56b9861d99be2838e8504884af4d30b909b1911639dd0c5ad47c557a0773155d4d303000000046a5151abffffffff9fdb84b77c326921a8266854f7bbd5a71305b54385e747fe41af8a397e78b7fa010000000863acac6a51ab00ac0d2e9b9d049b8173010000000007ac53526a650063ba9b7e010000000008526a00525263acac0ab3fd030000000000ea8a0303000000000200aca61a97b9", "", 1, -1276952681, "b6ed4a3721be3c3c7305a5128c9d418efa58e419580cec0d83f133a93e3a22c5"],
+	["a7721d94021652d90c79aaf5022d98219337d50f836382403ed313adb1116ba507ac28b0b0010000000551ac6300ab89e6d64a7aa81fb9595368f04d1b36d7020e7adf5807535c80d015f994cce29554fe869b01000000065353ab636500ffffffff024944c90100000000046300635369df9f01000000000000000000", "656a536551ab", 0, -1740151687, "935892c6f02948f3b08bcd463b6acb769b02c1912be4450126768b055e8f183a"],
+	["2f7353dd02e395b0a4d16da0f7472db618857cd3de5b9e2789232952a9b154d249102245fd030000000151617fd88f103280b85b0a198198e438e7cab1a4c92ba58409709997cc7a65a619eb9eec3c0200000003636aabffffffff0397481c0200000000045300636a0dc97803000000000009d389030000000003ac6a53134007bb", "0000536552526a", 0, -1912746174, "30c4cd4bd6b291f7e9489cc4b4440a083f93a7664ea1f93e77a9597dab8ded9c"],
+	["7d95473604fd5267d0e1bb8c9b8be06d7e83ff18ad597e7a568a0aa033fa5b4e1e2b6f1007020000000465006a6affffffffaee008503bfc5708bd557c7e78d2eab4878216a9f19daa87555f175490c40aaf000000000263abffffffffabd74f0cff6e7ceb9acc2ee25e65af1abcebb50c08306e6c78fa8171c37613dd010000000552acacababffffffff54a3069393f7930fa1b331cdff0cb945ec21c11d4605d8eedba1d3e094c6ae1f01000000026300ffffffff0182edeb050000000009526353ab5153530065a247e8cd", "51516aab00", 2, -426210430, "2707ca714af09494bb4cf0794abe33c6cba5f29891d619e76070269d1fa8e690"],
+	["221d4718023d9ca9fe1af178dbfce02b2b369bf823ea3f43f00891b7fef98e215c06b94fdd000000000951005153ab000051acffffffffb1c7ad1c64b7441bf5e70cd0f6eb4ec96821d67fc4997d9e6dfdceadecd36dde01000000070051536a635153ffffffff04e883cd00000000000851ab536553ab0052bbb2f70400000000002f1b2e03000000000165259fcb00000000000010dbde99", "ab", 1, 665721280, "4abce77432a86dfe608e7c1646c18b5253a373392ff962e288e3ab96bba1ba1d"],
+	["6f66c0b3013e6ae6aabae9382a4326df31c981eac169b6bc4f746edaa7fc1f8c796ef4e374000000000665ab6aabac6affffffff0191c8d6030000000002525300000000", "6a5352516a635352ab", 0, -1299629906, "48411efeb133c6b7fec4e7bdbe613f827093cb06ea0dbcc2ffcfde3a9ac4356c"],
+	["89e7928c04363cb520eff4465251fd8e41550cbd0d2cdf18c456a0be3d634382abcfd4a2130200000006ac516a6a656355042a796061ed72db52ae47d1607b1ceef6ca6aea3b7eea48e7e02429f382b378c4e51901000000085351ab6352ab5252ffffffff53631cbda79b40183000d6ede011c778f70147dc6fa1aed3395d4ce9f7a8e69701000000096a6553ab52516a52abad0de418d80afe059aab5da73237e0beb60af4ac490c3394c12d66665d1bac13bdf29aa8000000000153f2b59ab6027a33eb040000000007005351ac5100ac88b941030000000003ab0052e1e8a143", "63656a", 0, 1258533326, "b575a04b0bb56e38bbf26e1a396a76b99fb09db01527651673a073a75f0a7a34"],
+	["ca356e2004bea08ec2dd2df203dc275765dc3f6073f55c46513a588a7abcc4cbde2ff011c7020000000553525100003aefec4860ef5d6c1c6be93e13bd2d2a40c6fb7361694136a7620b020ecbaca9413bcd2a030000000965ac00536352535100ace4289e00e97caaea741f2b89c1143060011a1f93090dc230bee3f05e34fbd8d8b6c399010000000365526affffffff48fc444238bda7a757cb6a98cb89fb44338829d3e24e46a60a36d4e24ba05d9002000000026a53ffffffff03d70b440200000000056a6a526aac853c97010000000002515335552202000000000351635300000000", "0052", 3, -528192467, "fc93cc056c70d5e033933d730965f36ad81ef64f1762e57f0bc5506c5b507e24"],
+	["82d4fa65017958d53e562fac073df233ab154bd0cf6e5a18f57f4badea8200b217975e31030200000004636aab51ac0891a204227cc9050000000006635200655365bfef8802000000000865650051635252acfc2d09050000000006ab65ac51516380195e030000000007ac52525352510063d50572", "53", 0, -713567171, "e095003ca82af89738c1863f0f5488ec56a96fb81ea7df334f9344fcb1d0cf40"],
+	["75f6949503e0e47dd70426ef32002d6cdb564a45abedc1575425a18a8828bf385fa8e808e600000000036aabab82f9fd14e9647d7a1b5284e6c55169c8bd228a7ea335987cef0195841e83da45ec28aa2e0300000002516350dc6fe239d150efdb1b51aa288fe85f9b9f741c72956c11d9dcd176889963d699abd63f0000000001ab429a63f502777d20010000000007abac52ac516a53d081d9020000000003acac630c3cc3a8", "535152516551510000", 1, 973814968, "c6ec1b7cb5c16a1bfd8a3790db227d2acc836300534564252b57bd66acf95092"],
+	["24f24cd90132b2162f938f1c22d3ca5e7daa83515883f31a61a5177aebf99d7db6bdfc398c010000000163ffffffff01d5562d0100000000016300000000", "5265ac5165ac5252ab", 0, 1055129103, "5eeb03e03806cd7bfd44bbba69c30f84c2c5120df9e68cd8facc605fcfbc9693"],
+	["5ff2cac201423064a4d87a96b88f1669b33adddc6fa9acdc840c0d8a243671e0e6de49a5b00300000005ac6353655353b91db50180db5a03000000000663535151006a047a3aff", "52ab51ab5365005163", 0, -1336626596, "b8db8d57fe40ab3a99cf2f8ed57da7a65050fcc1d34d4280e25faf10108d3110"],
+	["10011f150220ad76a50ccc7bb1a015eda0ff987e64cd447f84b0afb8dc3060bdae5b36a6900200000000ffffffff1e92dd814dfafa830187bc8e5b9258de2445ec07b02c420ee5181d0b203bb334000000000565ab536a65ffffffff0124e65401000000000800ab636553ab53ac00000000", "53abab0051", 0, 440222748, "c6675bf229737e005b5c8ffa6f81d9e2c4396840921b6151316f67c4315a4270"],
+	["8b95ec900456648d820a9b8df1d8f816db647df8a8dc9f6e7151ebf6079d90ee3f6861352a02000000085200ab00ac535151ffffffff039b10b845f961225ac0bcaac4f5fe1991029a051aa3d06a3811b5762977a67403000000035252abffffffff8559d65f40d5e261f45aec8aad3d2c56c6114b22b26f7ee54a06f0881be3a7f5010000000765635252536363ffffffff38f8b003b50f6412feb2322b06b270197f81ad69c36af02ca5008b94eee5f650020000000165ffffffff01ae2b00010000000001638eb153a2", "0053ab5300ac53", 2, 1266056769, "205f3653f0142b35ce3ef39625442efebae98cde8cbf0516b97b51073bb0479f"],
+	["babbb7ea01ab5d584727cb44393b17cf66521606dc81e25d85273be0d57bad43e8f6b6d43501000000036a656aba83a68803fb0f4a000000000005536353ab633fcfe4020000000009ac00acab6351006a65182a0c03000000000453ac5363bee74f44", "536a6a6a6365ac51ab", 0, -799187625, "3275e98dca37243b977525a07b5d8e369d6c3bdc08cb948029a635547d0d1a4e"],
+	["e86a24bc03e4fae784cdf81b24d120348cb5e52d937cd9055402fdba7e43281e482e77a1c100000000046363006affffffffa5447e9bdcdab22bd20d88b19795d4c8fb263fbbf7ce8f4f9a85f865953a6325020000000663ac53535253ffffffff9f8b693bc84e0101fc73748e0513a8cecdc264270d8a4ee1a1b6717607ee1eaa00000000026a513417bf980158d82c020000000009005253005351acac5200000000", "6353516365536a6a", 2, -563792735, "508129278ef07b43112ac32faf00170ad38a500eed97615a860fd58baaad174b"],
+	["53bd749603798ed78798ef0f1861b498fc61dcee2ee0f2b37cddb115b118e73bc6a5a47a0201000000096a63656a6aab6a000007ff674a0d74f8b4be9d2e8e654840e99d533263adbdd0cf083fa1d5dd38e44d2d163d900100000007abab5251ac6a51c8b6b63f744a9b9273ccfdd47ceb05d3be6400c1ed0f7283d32b34a7f4f0889cccf06be30000000009516a52636551ab516a9ac1fe63030c677e05000000000027bc610000000000086565636a635100526e2dc60200000000015300000000", "6552536a515351ab", 1, -1617066878, "fe516df92299e995b8e6489be824c6839543071ec5e9286060b2600935bf1f20"],
+	["691bf9fc028ca3099020b79184e70039cf53b3c7b3fe695d661fd62d7b433e65feda2150610000000003ac63abffffffff2c814c15b142bc944192bddccb90a392cd05b968b599c1d8cd99a55a28a243fd0100000009ab5300526a5200abac98516a5803dfd3540500000000046552ac522838120100000000040053ab6a4409a903000000000665636a5300658759621b", "65ac5165ab", 0, -359941441, "d582c442e0ecc400c7ba33a56c93ad9c8cfd45af820350a13623594b793486f0"],
+	["536bc5e60232eb60954587667d6bcdd19a49048d67a027383cc0c2a29a48b960dc38c5a0370300000005ac636300abffffffff8f1cfc102f39b1c9348a2195d496e602c77d9f57e0769dabde7eaaedf9c69e250100000006acabab6a6351ffffffff0432f56f0400000000046a5365517fd54b0400000000035265539484e4050000000003536a5376dc25020000000008ac536aab6aab536ab978e686", "ac0051006a006a006a", 0, -273074082, "f151f1ec305f698d9fdce18ea292b145a58d931f1518cf2a4c83484d9a429638"],
+	["74606eba01c2f98b86c29ba5a32dc7a7807c2abe6ed8d89435b3da875d87c12ae05329e6070200000003510052ffffffff02a1e2c4020000000006516563526a63c68bae04000000000952ab6363ab00006363fe19ae4f", "63ababacac5365", 0, 112323400, "d1b1d79001b4a0324962607b739972d6f39c1493c4500ce814fd3bd72d32a5a0"],
+	["2ed805e20399e52b5bcc9dc075dad5cf19049ff5d7f3de1a77aee9288e59c5f4986751483f020000000165ffffffff967531a5726e7a653a9db75bd3d5208fa3e2c5e6cd5970c4d3aba84eb644c72c0300000000ffffffffd79030d20c65e5f8d3c55b5692e5bdaa2ae78cfa1935a0282efb97515feac43f030000000400006365261ab88c02bdf66a000000000003ab6351d6ad8b000000000005525152abac00000000", "630053ab5265", 0, 2072814938, "1d25d16d84d5793be1ad5cda2de9c9cf70e04a66c3dae618f1a7ca4026198e7f"],
+	["fab796ee03f737f07669160d1f1c8bf0800041157e3ac7961fea33a293f976d79ce49c02ab0200000003ac5252eb097ea1a6d1a7ae9dace338505ba559e579a1ee98a2e9ad96f30696d6337adcda5a85f403000000096500abab656a6a656396d5d41a9b11f571d91e4242ddc0cf2420eca796ad4882ef1251e84e42b930398ec69dd80100000005526551ac6a8e5d0de804f763bb0400000000015288271a010000000001acf2bf2905000000000300ab51c9641500000000000952655363636365ac5100000000", "00ac536552", 0, -1854521113, "f3bbab70b759fe6cfae1bf349ce10716dbc64f6e9b32916904be4386eb461f1f"],
+	["f2b539a401e4e8402869d5e1502dbc3156dbce93583f516a4947b333260d5af1a34810c6a00200000003525363ffffffff01d305e2000000000005acab535200a265fe77", "", 0, -1435650456, "41617b27321a830c712638dbb156dae23d4ef181c7a06728ccbf3153ec53d7dd"],
+	["9f10b1d8033aee81ac04d84ceee0c03416a784d1017a2af8f8a34d2f56b767aea28ff88c8f02000000025352ffffffff748cb29843bea8e9c44ed5ff258df1faf55fbb9146870b8d76454786c4549de100000000016a5ba089417305424d05112c0ca445bc7107339083e7da15e430050d578f034ec0c589223b0200000007abac53ac6565abffffffff025a4ecd010000000006636563ab65ab40d2700000000000056a6553526333fa296c", "", 0, -395044364, "20fd0eee5b5716d6cbc0ddf852614b686e7a1534693570809f6719b6fcb0a626"],
+	["ab81755f02b325cbd2377acd416374806aa51482f9cc5c3b72991e64f459a25d0ddb52e66703000000036a00ab8727056d48c00cc6e6222be6608c721bc2b1e69d0ffbadd51d131f05ec54bcd83003aac5000000000003f2cdb60454630e020000000007526aac63000000e9e25c040000000003516a0088c97e0000000000076a535265655263771b5805000000000851ab00ac6565515100000000", "5151ab00ac", 0, -230931127, "ba0a2c987fcdd74b6915f6462f62c3f126a0750aa70048f7aa20f70726e6a20b"],
+	["7a17e0ef0378dab4c601240639139335da3b7d684600fa682f59b7346ef39386fe9abd69350000000004ac5252ab807f26fb3249326813e18260a603b9ad66f41f05eaa8146f66bcca452162a502aac4aa8b02000000026a534ea460faa7e3d7854ec6c70d7e797025697b547ec500b2c09c873b4d5517767d3f3720660300000000ffffffff01b12e7a02000000000900ab006aab65656a63991c03e2", "6aab6a", 1, -1577994103, "62cd3413d9d819fb7355336365cf8a2a997f7436cc050a7143972044343b3281"],
+	["ff2ecc09041b4cf5abb7b760e910b775268abee2792c7f21cc5301dd3fecc1b4233ee70a2c0200000009acac5300006a51526affffffffeb39c195a5426afff38379fc85369771e4933587218ef4968f3f05c51d6b7c92000000000165453a5f039b8dbef7c1ffdc70ac383b481f72f99f52b0b3a5903c825c45cfa5d2c0642cd50200000001654b5038e6c49daea8c0a9ac8611cfe904fc206dad03a41fb4e5b1d6d85b1ecad73ecd4c0102000000096a51000053ab656565bdb5548302cc719200000000000452655265214a3603000000000300ab6a00000000", "52516a006a63", 1, -2113289251, "37ed6fae36fcb3360c69cac8b359daa62230fc1419b2cf992a32d8f3e079dcff"],
+	["70a8577804e553e462a859375957db68cfdf724d68caeacf08995e80d7fa93db7ebc04519d02000000045352ab53619f4f2a428109c5fcf9fee634a2ab92f4a09dc01a5015e8ecb3fc0d9279c4a77fb27e900000000006ab6a51006a6affffffff3ed1a0a0d03f25c5e8d279bb5d931b7eb7e99c8203306a6c310db113419a69ad010000000565516300abffffffff6bf668d4ff5005ef73a1b0c51f32e8235e67ab31fe019bf131e1382050b39a630000000004536a6563ffffffff02faf0bb00000000000163cf2b4b05000000000752ac635363acac15ab369f", "ac", 0, -1175809030, "1c9d6816c20865849078f9777544b5ddf37c8620fe7bd1618e4b72fb72dddca1"],
+	["a3604e5304caa5a6ba3c257c20b45dcd468f2c732a8ca59016e77b6476ac741ce8b16ca8360200000004acac6553ffffffff695e7006495517e0b79bd4770f955040610e74d35f01e41c9932ab8ccfa3b55d0300000007ac5253515365acffffffff6153120efc5d73cd959d72566fc829a4eb00b3ef1a5bd3559677fb5aae116e38000000000400abab52c29e7abd06ff98372a3a06227386609adc7665a602e511cadcb06377cc6ac0b8f63d4fdb03000000055100acabacffffffff04209073050000000009ab5163ac525253ab6514462e05000000000952abacab636300656a20672c0400000000025153b276990000000000056565ab6a5300000000", "5351", 0, 1460890590, "249c4513a49076c6618aabf736dfd5ae2172be4311844a62cf313950b4ba94be"],
+	["c6a72ed403313b7d027f6864e705ec6b5fa52eb99169f8ea7cd884f5cdb830a150cebade870100000009ac63ab516565ab6a51ffffffff398d5838735ff43c390ca418593dbe43f3445ba69394a6d665b5dc3b4769b5d700000000075265acab515365ffffffff7ee5616a1ee105fd18189806a477300e2a9cf836bf8035464e8192a0d785eea3030000000700ac6a51516a52ffffffff018075fd0000000000015100000000", "005251acac5252", 2, -656067295, "2cc1c7514fdc512fd45ca7ba4f7be8a9fe6d3318328bc1a61ae6e7675047e654"],
+	["93c12cc30270fc4370c960665b8f774e07942a627c83e58e860e38bd6b0aa2cb7a2c1e060901000000036300abffffffff4d9b618035f9175f564837f733a2b108c0f462f28818093372eec070d9f0a5440300000001acffffffff039c2137020000000001525500990100000000055265ab636a07980e0300000000005ba0e9d1", "656a5100", 1, 18954182, "6beca0e0388f824ca33bf3589087a3c8ad0857f9fe7b7609ae3704bef0eb83e2"],
+	["97bddc63015f1767619d56598ad0eb5c7e9f880b24a928fea1e040e95429c930c1dc653bdb0100000008ac53acac00005152aaa94eb90235ed10040000000000287bdd0400000000016a8077673a", "acac6a536352655252", 0, -813649781, "5990b139451847343c9bb89cdba0e6daee6850b60e5b7ea505b04efba15f5d92"],
+	["cc3c9dd303637839fb727270261d8e9ddb8a21b7f6cbdcf07015ba1e5cf01dc3c3a327745d0300000000d2d7804fe20a9fca9659a0e49f258800304580499e8753046276062f69dbbde85d17cd2201000000096352536a520000acabffffffffbc75dfa9b5f81f3552e4143e08f485dfb97ae6187330e6cd6752de6c21bdfd21030000000600ab53650063ffffffff0313d0140400000000096565515253526aacac167f0a040000000008acab00535263536a9a52f8030000000006abab5151ab63f75b66f2", "6a635353636a65ac65", 1, 377286607, "dbc7935d718328d23d73f8a6dc4f53a267b8d4d9816d0091f33823bd1f0233e9"],
+	["236f91b702b8ffea3b890700b6f91af713480769dda5a085ae219c8737ebae90ff25915a3203000000056300ac6300811a6a10230f12c9faa28dae5be2ebe93f37c06a79e76214feba49bb017fb25305ff84eb020000000100ffffffff041e351703000000000351ac004ff53e050000000003ab53636c1460010000000000cb55f701000000000651520051ab0000000000", "acac636a6aac5300", 0, 406448919, "793a3d3c37f6494fab79ff10c16702de002f63e34be25dd8561f424b0ea938c4"],
+	["22e10d2003ab4ea9849a2801921113583b7c35c3710ff49a6003489395789a7cfb1e6051900100000006526a65535151ffffffff82f21e249ec60db33831d33b9ead0d56f6496db64337dcb7f1c3327c47729c4a020000000253abffffffff138f098f0e6a4cf51dc3e7a3b749f487d1ebde71b73b731d1d02ad1180ac7b8c02000000036563acda215011027a9484020000000007635165530000ac4bf6cb0400000000066aacabab65ab3ce3f32c", "ab0052ab", 2, 1136359457, "b5bd080bbcb8cd652f440484311d7a3cb6a973cd48f03c5c00fd6beb52dfc061"],
+	["c47d5ad60485cb2f7a825587b95ea665a593769191382852f3514a486d7a7a11d220b62c54000000000663655253acab8c3cf32b0285b040e50dcf6987ddf7c385b3665048ad2f9317b9e0c5ba0405d8fde4129b00000000095251ab00ac65635300ffffffff549fe963ee410d6435bb2ed3042a7c294d0c7382a83edefba8582a2064af3265000000000152fffffffff7737a85e0e94c2d19cd1cde47328ece04b3e33cd60f24a8a345da7f2a96a6d0000000000865ab6a0051656aab28ff30d5049613ea020000000005ac51000063f06df1050000000008ac63516aabac5153afef5901000000000700656500655253688bc00000000000086aab5352526a53521ff1d5ff", "51ac52", 2, -1296011911, "0c1fd44476ff28bf603ad4f306e8b6c7f0135a441dc3194a6f227cb54598642a"],
+	["0b43f122032f182366541e7ee18562eb5f39bc7a8e5e0d3c398f7e306e551cdef773941918030000000863006351ac51acabffffffffae586660c8ff43355b685dfa8676a370799865fbc4b641c5a962f0849a13d8250100000005abab63acabffffffff0b2b6b800d8e77807cf130de6286b237717957658443674df047a2ab18e413860100000008ab6aac655200ab63ffffffff04f1dbca03000000000800635253ab656a52a6eefd0300000000036365655d8ca90200000000005a0d530400000000015300000000", "65ac65acac", 0, 351448685, "86f26e23822afd1bdfc9fff92840fc1e60089f12f54439e3ab9e5167d0361dcf"],
+	["4b0ecc0c03ba35700d2a30a71f28e432ff6ac7e357533b49f4e97cf28f1071119ad6b97f3e0300000008acab516363ac63acffffffffcd6a2019d99b5c2d639ddca0b1aa5ea7c1326a071255ea226960bd88f45ca57d00000000085253655363005353ffffffffba257635191c9f216de3277be548cb5a2313114cb1a4c563b03b4ef6c0f4f7040300000001abda542edf0495cdc40100000000026353c049e903000000000752516a53ab65512b0f9304000000000963ab516aac65516552fa9ece050000000009acab6500005152530000000000", "65ab51525352510052", 1, -1355414590, "3cd85f84aae6d702436f3f9b8980adcc1f8f202e957759540a27da0a32fc6c87"],
+	["adaac0a803f66811346271c733036d6e0d45e15a9b602092e2e04ad93564f196e7f020b088000000000600526a636a00700ec3f9db07a3a6ce910bf318c7ec87a876e1f2a3366cc69f20cde09203b99c1cb9d15800000000050000ac636a4d0de554ebe95c6cc14faf5ff6361d1deba9474b8b0fd3b93c011cd96aec783abb3f36830200000005ab65005251ffffffff0464eb10050000000007520000ab6a65ab1beaa80300000000005a2f31050000000006526aab65ac52ba7db10000000000045251ab6a0cfb46e7", "ab0051ac52636a", 1, -184733716, "961ff413850336d3987c550404fc1d923266ca36cc9ffee7113edb3a9fea7f30"],
+	["af1c4ab301ec462f76ee69ba419b1b2557b7ded639f3442a3522d4f9170b2d6859765c3df402000000016affffffff01a5ca6c000000000008ab52536aab00005300000000", "6a6351", 0, 110304602, "e88ed2eea9143f2517b15c03db00767eb01a5ce12193b99b964a35700607e5f4"],
+	["0bfd34210451c92cdfa02125a62ba365448e11ff1db3fb8bc84f1c7e5615da40233a8cd368010000000252ac9a070cd88dec5cf9aed1eab10d19529720e12c52d3a21b92c6fdb589d056908e43ea910e0200000009ac516a52656a6a5165ffffffffc3edcca8d2f61f34a5296c405c5f6bc58276416c720c956ff277f1fb81541ddd00000000030063abffffffff811247905cdfc973d179c03014c01e37d44e78f087233444dfdce1d1389d97c302000000065163000063ab1724a26e02ca37c902000000000851ab53525352ac529012a90100000000085200525253535353fa32575b", "5352ac6351", 1, -1087700448, "b8f1e1f35e3e1368bd17008c756e59cced216b3c699bcd7bebdb5b6c8eec4697"],
+	["2c84c0640487a4a695751d3e4be48019dbaea85a6e854f796881697383ea455347d2b2769001000000055265526500ffffffff6aac176d8aa00778d496a7231eeb7d3334f20c512d3db1683276402100d98de5030000000700536a5263526ac1ee9ceb171c0c984ebaf12c234fd1487fbf3b3d73aa0756907f26837efba78d1bed33200300000001ab4d9e8ec0bed837cb929bbed76ee848959cec59de44bd7667b7631a744f880d5c71a20cfd0100000007005363515300abffffffff023753fb0000000000036565532d3873050000000009005152ab6a63acab5200000000", "ab650053ab", 0, -877941183, "c49af297dffe2d80deddf10ceea84b99f8554bd2d55bbdc34e449728c31f0835"],
+	["1f7e4b1b045d3efa6cd7a11d7873a8bab886c19bd11fcb6712f0948f2db3a7be76ff76c8f100000000095265ab6a0065ac5363ffffffffdaafcfa6029336c997680a541725190f09a6f6da21e54560eca4b5b8ae987da1000000000952ac52acac52515165ffffffff825a38d3b1e5bb4d10f33653ab3ab6882c7abdaec74460257d1528ce7be3f98e0100000007526a006a656a63c14adc8f04953a5d3d3f89237f38b857dd357713896d36215f7e8b77b11d98ea3cdc93df02000000015212484f6104bfafae0300000000025263a2b0120000000000056563ab00516c4d2605000000000653ac6500655301cc93030000000002acab14643b1f", "63acac53ab", 0, 333824258, "18da6ceb011cd36f15ad7dd6c55ef07e6f6ed48881ce3bb31416d3c290d9a0e9"],
+	["467a3e7602e6d1a7a531106791845ec3908a29b833598e41f610ef83d02a7da3a1900bf2960000000005ab6a636353ffffffff031db6dac6f0bafafe723b9199420217ad2c94221b6880654f2b35114f44b1df010000000965ab52636a63ac6352ffffffff02b3b95c0100000000026300703216030000000001ab3261c0aa", "6a", 0, 2110869267, "3078b1d1a7713c6d101c64afe35adfae0977a5ab4c7e07a0b170b041258adbf2"],
+	["8713bc4f01b411149d575ebae575f5dd7e456198d61d238695df459dd9b86c4e3b2734b62e0300000004abac6363ffffffff03b58049050000000002ac653c714c04000000000953656a005151526a527b5a9e03000000000652ac5100525300000000", "52", 0, -647281251, "0e0bed1bf2ff255aef6e5c587f879ae0be6222ab33bd75ee365ec6fbb8acbe38"],
+	["f2ba8a8701b9c401efe3dd0695d655e20532b90ac0142768cee4a3bb0a89646758f544aa8102000000036a52527899f4e4040c6f0b030000000008636565ab530051ab52b60c000000000009515200ab630053ac53a49c5f040000000008ab53ab516300ab63fa27340300000000015100000000", "ac63abab5251", 0, -1328936437, "ab61497afd39e61fe06bc5677326919716f9b20083c9f3417dcea905090e0411"],
+	["b5a7df6102107beded33ae7f1dec0531d4829dff7477260925aa2cba54119b7a07d92d5a1d02000000046a516a52803b625c334c1d2107a326538a3db92c6c6ae3f7c3516cd90a09b619ec6f58d10e77bd6703000000056563006a63ffffffff0117484b03000000000853acab52526a65abc1b548a1", "ac006a525100", 0, 2074359913, "680336db57347d8183b8898cd27a83f1ba5884155aeae5ce20b4840b75e12871"],
+	["278cb16204b9dadf400266106392c4aa9df01ba03af988c8139dae4c1818ac009f13fc5f1a00000000065200ac656a52ffffffffd006bbebd8cbd7bdead24cddc9badfcc6bc0c2e63c037e5c29aa858f5d0f3e7d01000000046a0051acffffffffbc62a5f57e58da0b67956003ae81ac97cb4cbd1d694c914fc41515c008c4d8fd020000000165e329c844bcc16164be64b64a81cbf4ffd41ed2934e0daa0040ccb8365bab0b2a9e401c180300000003ab52abffffffff02588460030000000000a25a12030000000005535100005300000000", "6553ab6a5300acab51", 3, 989407546, "1c29f110576f4a3b257f67454d99dfc0dee62ef5517ca702848ce4bd2ea1a1d7"],
+	["49eb2178020a04fca08612c34959fd41447319c190fb7ffed9f71c235aa77bec28703aa1820200000003ac6353abaff326071f07ec6b77fb651af06e8e8bd171068ec96b52ed584de1d71437fed186aecf0300000001acffffffff03da3dbe02000000000652ac63ac6aab8f3b680400000000096a536a65636a53516a5175470100000000016500000000", "6a536365", 0, 1283691249, "c670219a93234929f662ecb9aa148a85a2d281e83f4e53d10509461cdea47979"],
+	["0f96cea9019b4b3233c0485d5b1bad770c246fe8d4a58fb24c3b7dfdb3b0fd90ea4e8e947f0300000006006a5163515303571e1e01906956030000000005ab635353abadc0fbbe", "acac", 0, -1491469027, "716a8180e417228f769dcb49e0491e3fda63badf3d5ea0ceeac7970d483dd7e2"],
+	["9a7d858604577171f5fe3f3fd3e5e039c4b0a06717a5381e9977d80e9f53e025e0f16d2877020000000752636565536353ffffffff5862bd028e8276e63f044be1dddcbb8d0c3fa097678308abf2b0f45104a93dbd0100000001531200667ba8fdd3b28e98a35da73d3ddfe51e210303d8eb580f923de988ee632d77793892030000000752526363526563ffffffffe9744eb44db2658f120847c77f47786d268c302120d269e6004455aa3ea5f5e20200000009ab6300636aab656551ffffffff03c61a3c020000000009ab516a6aab6aab53ab737f1a05000000000853acabab655365ab92a4a00400000000016367edf6c8", "535352ab", 3, 659348595, "d36ee79fc80db2e63e05cdc50357d186181b40ae20e3720878284228a13ee8b3"],
+	["148e68480196eb52529af8e83e14127cbfdbd4a174e60a86ac2d86eac9665f46f4447cf7aa01000000045200ac538f8f871401cf240c0300000000065252ab52656a5266cf61", "", 0, -344314825, "eacc47c5a53734d6ae3aedbc6a7c0a75a1565310851b29ef0342dc4745ceb607"],
+	["e2bc29d4013660631ba14ecf75c60ec5e9bed7237524d8c10f66d0675daa66d1492cb834530200000004ac510065e42d0c9e04f2b26c01000000000951525152acac65ababa35b7504000000000953ac6aac00650053ab94688c0400000000056365526553a1bced0300000000016a00000000", "65ab0063655353", 0, -888431789, "59a34b3ed3a1cce0b104de8f7d733f2d386ffc7445efae67680cd90bc915f7e0"],
+	["0c8a70d70494dca6ab05b2bc941b5b431c43a292bd8f2f02eab5e240a408ca73a676044a4103000000056a51ab006affffffff84496004e54836c035821f14439149f22e1db834f315b24588ba2f031511926c0100000000ffffffffbbc5e70ed1c3060ba1bfe99c1656a3158a7307c3ce8eb362ec32c668596d2bd30000000009636563635351abab00b039344c6fc4f9bec24322e45407af271b2d3dfec5f259ee2fc7227bc5285e22b3be85b40100000009ac00ab53abac6a5352e5ddfcff02d50231020000000005006a51536ab086d9020000000006ababac51ac6a00000000", "abab636565acac6a", 3, 241546088, "643a7b4c8d832e14d5c10762e74ec84f2c3f7ed96c03053157f1bed226614911"],
+	["f98f79cf0274b745e1d6f36da7cbe205a79132a7ad462bdc434cfb1dcd62a6977c3d2a5dbc010000000553516a5365ffffffff4f89f485b53cdad7fb80cc1b7e314b9735b9383bc92c1248bb0e5c6173a55c0d010000000353655293f9b014045ad96d02000000000963ac526a53ac636365f4c27904000000000952536563635152526a2788f0030000000002516aff5add01000000000863530051655351abd04716ba", "ab6552536a53", 1, -2128899945, "56d29f5e300ddfed2cd8dcce5d79826e193981d0b70dc7487772c8a0b3b8d7b1"],
+	["6c7913f902aa3f5f939dd1615114ce961beda7c1e0dd195be36a2f0d9d047c28ac62738c3a020000000453abac00ffffffff477bf2c5b5c6733881447ac1ecaff3a6f80d7016eee3513f382ad7f554015b970100000007ab6563acab5152ffffffff04e58fe1040000000009ab00526aabab526553e59790010000000002ab525a834b03000000000035fdaf0200000000086551ac65515200ab00000000", "63ac53", 1, 1285478169, "1536da582a0b6de017862445e91ba14181bd6bf953f4de2f46b040d351a747c9"],
+	["4624aa9204584f06a8a325c84e3b108cafb97a387af62dc9eab9afd85ae5e2c71e593a3b690200000003636a005eb2b44eabbaeca6257c442fea00107c80e32e8715a1293cc164a42e62ce14fea146220c020000000090b9ee38106e3310037bfc519fd209bdbd21c588522a0e96df5fba4e979392bc993bfe9f01000000086363636a635353ab6f1907d218ef6f3c729d9200e23c1dbff2df58b8b1282c6717b26cf760ee4c880d23f4d100000000086a516a536a525163ffffffff01d6f162050000000000ebbab208", "525365ab0053", 1, -1515409325, "6cf9cd409b7185b1f118171f0a34217af5b612ea54195ea186505b667c19337f"],
+	["16562fc503f1cf9113987040c408bfd4523f1512da699a2ca6ba122dc65677a4c9bf7763830000000003636552ffffffff1ec1fab5ff099d1c8e6b068156f4e39b5543286bab53c6d61e2582d1e07c96cf02000000045163656affffffffd0ef40003524d54c08cb4d13a5ee61c84fbb28cde9eca7a6d11ba3a9335d8c620100000007635153536a6300fbb84fc2012003a601000000000363ab6a00000000", "63636a006a6aab", 0, -1310262675, "1efbf3d37a92bc03d9eb950b792f307e95504f7c4998f668aa250707ebb752ac"],
+	["531665d701f86bacbdb881c317ef60d9cd1baeffb2475e57d3b282cd9225e2a3bf9cbe0ded01000000086300ac515263acabffffffff0453a8500100000000086353acab516a6565e5e9200500000000026a52a44caa00000000000453ac000065e41b0500000000076500ac0065526ab4476f4d", "006563006aab00636a", 0, 1770013777, "0898b26dd3ca08632a5131fa48eb55b44386d0c5070c24d6e329673d5e3693b8"],
+	["0f1227a20140655a3da36e413b9b5d108a866f6f147eb4940f032f5a89854eae6d7c3a91600100000009525363515153515253e37a79480161ab61020000000001ab00000000", "ab65005200", 0, -1996383599, "979782dc3f36d908d37d7e4046a38d306b4b08ddc60a5eba355fe3d6da1b29a9"],
+	["063ff6eb01aff98d0d2a6db224475010edb634c2f3b46257084676adeb84165a4ff8558d7601000000066353006a5165deb3262c042d109c0000000000076363ab52ac005200b9c4050000000007516300ac510063cfffc800000000000200639e815501000000000700526a52ac6365ac7b07b8", "656552abac6500", 0, -1559847112, "674a4bcb04247f8dc98780f1792cac86b8aee41a800fc1e6f5032f6e1dccde65"],
+	["3320f6730132f830c4681d0cae542188e4177cad5d526fae84565c60ceb5c0118e844f90bd030000000163ffffffff0257ec5a040000000005525251ac6538344d000000000002515200000000", "5352656a53ac516a65", 0, 788050308, "3afacaca0ef6be9d39e71d7b1b118994f99e4ea5973c9107ca687d28d8eba485"],
+	["c13aa4b702eedd7cde09d0416e649a890d40e675aa9b5b6d6912686e20e9b9e10dbd40abb1000000000863ab6353515351ac11d24dc4cc22ded7cdbc13edd3f87bd4b226eda3e4408853a57bcd1becf2df2a1671fd1600000000045165516affffffff01baea300100000000076aab52ab53005300000000", "0065", 0, -1195908377, "241a23e7b1982d5f78917ed97a8678087acbbffe7f624b81df78a5fe5e41e754"],
+	["d9a6f20e019dd1b5fae897fb472843903f9c3c2293a0ffb59cff2b413bae6eceab574aaf9d030000000663ab006a515102f54939032df5100100000000056a51ab65530ec28f010000000004ac5100007e874905000000000651005265ac6a00000000", "abacab63acacabab", 0, 271463254, "1326a46f4c21e7619f30a992719a905aa1632aaf481a57e1cbd7d7c22139b41e"],
+	["157c81bf0490432b3fcb3f9a5b79e5f91f67f05efb89fa1c8740a3fe7e9bdc18d7cb6acd2203000000026351ffffffff912e48e72bbcf8a540b693cf8b028e532a950e6e63a28801f6eaad1afcc52ad00000000000b1a4b170a2b9e60e0cad88a0085137309f6807d25d5afb5c1e1d32aa10ba1cdf7df596dd0000000009525165656a51ab65ab3674fba32a76fe09b273618d5f14124465933f4190ba4e0fd09d838daafc6223b31642ac00000000086a53536551ac6565ffffffff01fe9fb6030000000008ab51656a5165636a00000000", "ab00ab6a6551", 3, -64357617, "1ddaab7f973551d71f16bd70c4c4edbf7225e64e784a6da0ee7f7a9fe4f12a0b"],
+	["a2692fff03b2387f5bacd5640c86ba7df574a0ee9ed7f66f22c73cccaef3907eae791cbd230200000004536363abffffffff4d9fe7e5b375de88ba48925d9b2005447a69ea2e00495a96eafb2f144ad475b40000000008000053000052636537259bee3cedd3dcc07c8f423739690c590dc195274a7d398fa196af37f3e9b4a1413f810000000006ac63acac52abffffffff04c65fe60200000000075151536365ab657236fc020000000009005263ab00656a6a5195b8b6030000000007ac5165636aac6a7d7b66010000000002acab00000000", "51", 2, -826546582, "925037c7dc7625f3f12dc83904755a37016560de8e1cdd153c88270a7201cf15"],
+	["2c5b003201b88654ac2d02ff6762446cb5a4af77586f05e65ee5d54680cea13291efcf930d0100000005ab536a006a37423d2504100367000000000004536a515335149800000000000152166aeb03000000000452510063226c8e03000000000000000000", "635251", 0, 1060344799, "7e058ca5dd07640e4aae7dea731cfb7d7fef1bfd0d6d7b6ce109d041f4ca2a31"],
+	["f981b9e104acb93b9a7e2375080f3ea0e7a94ce54cd8fb25c57992fa8042bdf4378572859f0100000002630008604febba7e4837da77084d5d1b81965e0ea0deb6d61278b6be8627b0d9a2ecd7aeb06a0300000005ac5353536a42af3ef15ce7a2cd60482fc0d191c4236e66b4b48c9018d7dbe4db820f5925aad0e8b52a0300000008ab0063510052516301863715efc8608bf69c0343f18fb81a8b0c720898a3563eca8fe630736c0440a179129d03000000086aac6a52ac6a63ac44fec4c00408320a03000000000062c21c030000000007ac6a655263006553835f0100000000015303cd60000000000005535263536558b596e0", "00", 0, -2140385880, "49870a961263354c9baf108c6979b28261f99b374e97605baa532d9fa3848797"],
+	["e7416df901269b7af14a13d9d0507709b3cd751f586ce9d5da8d16a121e1bd481f5a086e1103000000056aab005200ffffffff01aa269c040000000006acac6a6a5263ee718de6", "ab525363", 0, 1309186551, "eea7d2212bda2d408fff146f9ae5e85e6b640a93b9362622bb9d5e6e36798389"],
+	["402a815902193073625ab13d876190d1bbb72aecb0ea733c3330f2a4c2fe6146f322d8843a0300000008656aab0000535363fffffffff9dccdec5d8509d9297d26dfcb1e789cf02236c77dc4b90ebccbf94d1b5821150300000001510bf1f96a03c5c145000000000002ac6ae11b1c0100000000055163516a5239c8a600000000000365636300000000", "63536aacab", 0, -1811424955, "0090803a20102a778ab967a74532faee13e03b702083b090b1497bc2267ee2fe"],
+	["c4b702e502f1a54f235224f0e6de961d2e53b506ab45b9a40805d1dacd35148f0acf24ca5e00000000085200ac65ac53acabf34ba6099135658460de9d9b433b84a8562032723635baf21ca1db561dce1c13a06f4407000000000851ac006a63516aabffffffff02a853a603000000000163d17a67030000000005ab63006a5200000000", "ac5363515153", 1, 480734903, "5c46f7ac3d6460af0da28468fcc5b3c87f2b9093d0f837954b7c8174b4d7b6e7"],
+	["9b83f78704f492b9b353a3faad8d93f688e885030c274856e4037818848b99e490afef27770200000000ffffffff36b60675a5888c0ef4d9e11744ecd90d9fe9e6d8abb4cff5666c898fdce98d9e00000000056aab656352596370fca7a7c139752971e169a1af3e67d7656fc4fc7fd3b98408e607c2f2c836c9f27c030000000653ac51ab6300a0761de7e158947f401b3595b7dc0fe7b75fa9c833d13f1af57b9206e4012de0c41b8124030000000953656a53ab53510052242e5f5601bf83b301000000000465516a6300000000", "63515200ac656365", 3, -150879312, "9cf05990421ea853782e4a2c67118e03434629e7d52ab3f1d55c37cf7d72cdc4"],
+	["f492a9da04f80b679708c01224f68203d5ea2668b1f442ebba16b1aa4301d2fe5b4e2568f3010000000953005351525263ab65ffffffff93b34c3f37d4a66df255b514419105b56d7d60c24bf395415eda3d3d8aa5cd0101000000020065ffffffff9dba34dabdc4f1643b372b6b77fdf2b482b33ed425914bb4b1a61e4fad33cf390000000002ab52ffffffffbbf3dc82f397ef3ee902c5146c8a80d9a1344fa6e38b7abce0f157be7adaefae0000000009515351005365006a51ffffffff021359ba010000000000403fea0200000000095200ac6353abac635300000000", "00ac51acacac", 0, -2115078404, "fd44fc98639ca32c927929196fc3f3594578f4c4bd248156a25c04a65bf3a9f3"],
+	["2f73e0b304f154d3a00fde2fdd40e791295e28d6cb76af9c0fd8547acf3771a02e3a92ba37030000000852ac6351ab6565639aa95467b065cec61b6e7dc4d6192b5536a7c569315fb43f470078b31ed22a55dab8265f02000000080065636a6aab6a53ffffffff9e3addbff52b2aaf9fe49c67017395198a9b71f0aa668c5cb354d06c295a691a0100000000ffffffff45c2b4019abaf05c5e484df982a4a07459204d1343a6ee5badade358141f8f990300000007ac516a6aacac6308655cd601f3bc2f0000000000015200000000", "", 0, -2082053939, "9a95e692e1f78efd3e46bb98f178a1e3a0ef60bd0301d9f064c0e5703dc879c2"],
+	["5a60b9b503553f3c099f775db56af3456330f1e44e67355c4ab290d22764b9144a7b5f959003000000030052acbd63e0564decc8659aa53868be48c1bfcda0a8c9857b0db32a217bc8b46d9e7323fe9649020000000553ac6551abd0ecf806211db989bead96c09c7f3ec5f73c1411d3329d47d12f9e46678f09bac0dc383e0200000000ffffffff01494bb202000000000500516551ac00000000", "ac", 0, 1169947809, "62a36c6e8da037202fa8aeae03e533665376d5a4e0a854fc4624a75ec52e4eb1"],
+	["7e98d353045569c52347ca0ff2fdba608829e744f61eb779ffdb5830aae0e6d6857ab2690e03000000075365acab656352ffffffffa890dd37818776d12da8dca53d02d243ef23b4535c67016f4c58103eed85360f030000000093dbacdc25ca65d2951e047d6102c4a7da5e37f3d5e3c8b87c29b489360725dcd117ee2003000000056a6300ac53c7e99fa1dc2b8b51733034e6555f6d6de47dbbf1026effac7db80cb2080678687380dc1e02000000075352005263516affffffff04423272040000000008ab6353ab65510051e0f53b0500000000086300516552635152f74a5f04000000000853acab0053ab52ab0e8e5f00000000000951ac5363516a6aabab00000000", "6a5163ab52", 3, 890006103, "476868cecd1763c91dade98f17defa42d31049547df45acffa1cc5ae5c3d75d6"],
+	["e3649aa40405e6ffe377dbb1bbbb672a40d8424c430fa6512c6165273a2b9b6afa9949ec430200000007630052ab655153a365f62f2792fa90c784efe3f0981134d72aac0b1e1578097132c7f0406671457c332b84020000000353ab6ad780f40cf51be22bb4ff755434779c7f1def4999e4f289d2bd23d142f36b66fbe5cfbb4b01000000076a5252abac52ab1430ffdc67127c9c0fc97dcd4b578dab64f4fb9550d2b59d599773962077a563e8b6732c02000000016affffffff04cb2687000000000002ab636e320904000000000252acf70e9401000000000100dc3393050000000006ab0063536aacbc231765", "65520053", 3, -2016196547, "f64f805f0ff7f237359fa6b0e58085f3c766d1859003332223444fd29144112a"],
+	["1d033569040700441686672832b531ab55db89b50dc1f9fc00fb72218b652da9dcfbc83be901000000066551ac526a632b390f9ad068e5fdee6563e88e2a8e4e09763c861072713dc069893dc6bbc9db3f00e26502000000096a5363526565525252ffffffff8a36bdd0aaf38f6707592d203e14476ca9f259021e487135c7e8324244057ed90300000000ed3fb2a3dfd4d46b5f3603fe0148653911988457bd0ed7f742b07c452f5476c228ff9f600200000007526aac00525152ffffffff04b88e48030000000000c753d602000000000853510000006553518fda2603000000000853ac52acac5263534839f1030000000006ac006aacac5300000000", "516553635300ab0052", 1, 2075958316, "c2cefaec2293134acbcf6d2a8bf2b3eb42e4ec04ee8f8bf30ff23e65680677c1"],
+	["4c4be7540344050e3044f0f1d628039a334a7c1f7b4573469cfea46101d6888bb6161fe9710200000000ffffffffac85a4fdad641d8e28523f78cf5b0f4dc74e6c5d903c10b358dd13a5a1fd8a06000000000163e0ae75d05616b72467b691dc207fe2e65ea35e2eadb7e06ea442b2adb9715f212c0924f10200000000ffffffff0194ddfe02000000000265ac00000000", "00006500", 1, -479922562, "d66924d49f03a6960d3ca479f3415d638c45889ce9ab05e25b65ac260b51d634"],
+	["202c18eb012bc0a987e69e205aea63f0f0c089f96dd8f0e9fcde199f2f37892b1d4e6da90302000000055352ac6565ffffffff0257e5450100000000025300ad257203000000000000000000", "520052ac6a005265", 0, 168054797, "502967a6f999f7ee25610a443caf8653dda288e6d644a77537bcc115a8a29894"],
+	["32fa0b0804e6ea101e137665a041cc2350b794e59bf42d9b09088b01cde806ec1bbea077df0200000008515153650000006506a11c55904258fa418e57b88b12724b81153260d3f4c9f080439789a391ab147aabb0fa0000000007000052ac51ab510986f2a15c0d5e05d20dc876dd2dafa435276d53da7b47c393f20900e55f163b97ce0b800000000008ab526a520065636a8087df7d4d9c985fb42308fb09dce704650719140aa6050e8955fa5d2ea46b464a333f870000000009636300636a6565006affffffff01994a0d040000000002536500000000", "516563530065", 2, -163068286, "f58637277d2bc42e18358dc55f7e87e7043f5e33f4ce1fc974e715ef0d3d1c2a"],
+	["ae23424d040cd884ebfb9a815d8f17176980ab8015285e03fdde899449f4ae71e04275e9a80100000007ab006553530053ffffffff018e06db6af519dadc5280c07791c0fd33251500955e43fe4ac747a4df5c54df020000000251ac330e977c0fec6149a1768e0d312fdb53ed9953a3737d7b5d06aad4d86e9970346a4feeb5030000000951ab51ac6563ab526a67cabc431ee3d8111224d5ecdbb7d717aa8fe82ce4a63842c9bd1aa848f111910e5ae1eb0100000004ac515300bfb7e0d7048acddc030000000009636a5253636a655363a3428e040000000001525b99c6050000000004655265ab717e6e020000000000d99011eb", "ac6a6a516565", 1, -716251549, "b098eb9aff1bbd375c70a0cbb9497882ab51f3abfebbf4e1f8d74c0739dc7717"],
+	["030f44fc01b4a9267335a95677bd190c1c12655e64df74addc53b753641259af1a54146baa020000000152e004b56c04ba11780300000000026a53f125f001000000000251acd2cc7c03000000000763536563655363c9b9e50500000000015200000000", "ac", 0, -1351818298, "19dd32190ed2a37be22f0224a9b55b91e37290577c6c346d36d32774db0219a3"],
+	["c05f448f02817740b30652c5681a3b128322f9dc97d166bd4402d39c37c0b14506d8adb5890300000003536353ffffffffa188b430357055ba291c648f951cd2f9b28a2e76353bef391b71a889ba68d5fc02000000056565526a6affffffff02745f73010000000001ab3ec34c0400000000036aac5200000000", "516551510053", 0, -267877178, "3a1c6742d4c374f061b1ebe330b1e169a113a19792a1fdde979b53e094cc4a3c"],
+	["163ba45703dd8c2c5a1c1f8b806afdc710a2a8fc40c0138e2d83e329e0e02a9b6c837ff6b8000000000700655151ab6a522b48b8f134eb1a7e6f5a6fa319ce9d11b36327ba427b7d65ead3b4a6a69f85cda8bbcd22030000000563656552acffffffffdbcf4955232bd11eef0cc6954f3f6279675b2956b9bcc24f08c360894027a60201000000066500006500abffffffff04d0ce9d0200000000008380650000000000015233f360040000000003006aabedcf0801000000000000000000", "000065006500ac", 0, 216965323, "9afe3f4978df6a86e9a8ebd62ef6a9d48a2203f02629349f1864ef2b8b92fd55"],
+	["07f7f5530453a12ad0c7eb8fbc3f140c7ab6818144d67d2d8752600ca5d9a9358e2dff87d4000000000663526aab526a9e599c379d455e2da36d0cde88d931a863a3e97e01e93b9edb65856f3d958dc08b92b720000000000165bbc8d66dae3b1b170a6e2457f5b161465cb8706e0e6ffc6af55deb918365f14c5f40d4890100000000a7bd77c069ee4b48638e2363fcf2a86b02bea022047bd9fcb16d2b94ad068308d19b31cb00000000066aab5300ab529672aa8f01dbd8a205000000000663536353006a02e99901", "ac006351006a63ab63", 1, 119789359, "6629a1e75c6ae8f4f9d5f734246b6a71682a5ea57246040ef0584f6b97916175"],
+	["fe647f950311bf8f3a4d90afd7517df306e04a344d2b2a2fea368935faf11fa6882505890d0000000005ab5100516affffffff43c140947d9778718919c49c0535667fc6cc727f5876851cb8f7b6460710c7f60100000000ffffffffce4aa5d90d7ab93cbec2e9626a435afcf2a68dd693c15b0e1ece81a9fcbe025e0300000000ffffffff02f34806020000000002515262e54403000000000965635151ac655363636de5ce24", "6a005100ac516351", 2, 989643518, "818a7ceaf963f52b5c48a7f01681ac6653c26b63a9f491856f090d9d60f2ffe3"],
+	["a1050f8604d0f9d2feefcdb5051ae0052f38e21bf39daf583fd0c3900faa3eab5d431c0bbe030000000653536a005151683d27e5c6e0da8f22125823f32d5d98477d8098ef36263b9694d61d4d85d3f2ac02b7570200000007000052005165abffffffff0cad981542bcb54a87d9400aa63e514c7c6fab7158c2b1fb37821ea755eb162a0200000000b94feb5100e5ef3bf8ed8d43356c8a8d5ac6c7e80d7ff6040f4f0aa19abbe783f4f461240200000007636500000052655686fd70042be3ad02000000000465ab636a15680b000000000004acac53511277c705000000000452635252d27a0102000000000000000000", "6a6aacab65655251", 1, -982144648, "dfcf484111801989eb6df8dc2bafb944d7365ffeb36a575a08f3270d3ef24c9f"],
+	["cef7316804c3e77fe67fc6207a1ea6ae6eb06b3bf1b3a4010a45ae5c7ad677bb8a4ebd16d90200000009ac536a5152ac5263005301ab8a0da2b3e0654d31a30264f9356ba1851c820a403be2948d35cafc7f9fe67a06960300000006526a63636a53ffffffffbada0d85465199fa4232c6e4222df790470c5b7afd54704595a48eedd7a4916b030000000865ab63ac006a006ab28dba4ad55e58b5375053f78b8cdf4879f723ea4068aed3dd4138766cb4d80aab0aff3d0300000003ac6a00ffffffff010f5dd6010000000006ab006aab51ab00000000", "", 1, 889284257, "d0f32a6db43378af84b063a6706d614e2d647031cf066997c48c04de3b493a94"],
+	["7b3ff28004ba3c7590ed6e36f45453ebb3f16636fe716acb2418bb2963df596a50ed954d2e03000000065251515265abffffffff706ee16e32e22179400c9841013971645dabf63a3a6d2d5feb42f83aa468983e030000000653ac51ac5152ffffffffa03a16e5e5de65dfa848b9a64ee8bf8656cc1f96b06a15d35bd5f3d32629876e020000000043c1a3965448b3b46f0f0689f1368f3b2981208a368ec5c30defb35595ef9cf95ffd10e902000000036aac65253a5bbe042e907204000000000800006565656352634203b4020000000002656336b3b7010000000001ab7a063f0100000000026500a233cb76", "006551636a53ac5251", 1, -1144216171, "68c7bd717b399b1ee33a6562a916825a2fed3019cdf4920418bb72ffd7403c8c"],
+	["d5c1b16f0248c60a3ddccf7ebd1b3f260360bbdf2230577d1c236891a1993725e262e1b6cb000000000363636affffffff0a32362cfe68d25b243a015fc9aa172ea9c6b087c9e231474bb01824fd6bd8bc0300000005ab52ab516affffffff0420d9a70200000000045152656a45765d0000000000055252536a5277bad100000000000252ab3f3f3803000000000463acac5200000000", "52636a52ab65", 1, 1305123906, "978dc178ecd03d403b048213d904653979d11c51730381c96c4208e3ea24243a"],
+	["1be8ee5604a9937ebecffc832155d9ba7860d0ca451eaced58ca3688945a31d93420c27c460100000006abac5300535288b65458af2f17cbbf7c5fbcdcfb334ffd84c1510d5500dc7d25a43c36679b702e850f7c0200000003005300ffffffff7c237281cb859653eb5bb0a66dbb7aeb2ac11d99ba9ed0f12c766a8ae2a2157203000000086aabac526365acabfffffffff09d3d6639849f442a6a52ad10a5d0e4cb1f4a6b22a98a8f442f60280c9e5be80200000007ab00ab6565ab52ffffffff0398fe83030000000005526aababacbdd6ec010000000005535252ab6a82c1e6040000000001652b71c40c", "6563526353656351", 2, -853634888, "0d936cceda2f56c7bb87d90a7b508f6208577014ff280910a710580357df25f3"],
+	["9e0f99c504fbca858c209c6d9371ddd78985be1ab52845db0720af9ae5e2664d352f5037d4010000000552ac53636affffffff0e0ce866bc3f5b0a49748f597c18fa47a2483b8a94cef1d7295d9a5d36d31ae7030000000663515263ac635bb5d1698325164cdd3f7f3f7831635a3588f26d47cc30bf0fefd56cd87dc4e84f162ab702000000036a6365ffffffff85c2b1a61de4bcbd1d5332d5f59f338dd5e8accbc466fd860f96eef1f54c28ec030000000165ffffffff04f5cabd010000000007000052ac526563c18f1502000000000465510051dc9157050000000008655363ac525253ac506bb600000000000865656a53ab63006a00000000", "006a6a0052", 0, 1186324483, "2f9b7348600336512686e7271c53015d1cb096ab1a5e0bce49acd35bceb42bc8"],
+	["11ce51f90164b4b54b9278f0337d95c50d16f6828fcb641df9c7a041a2b274aa70b1250f2b0000000008ab6a6a65006551524c9fe7f604af44be050000000005525365006521f79a0300000000015306bb4e04000000000265ac99611a05000000000765acab656500006dc866d0", "", 0, -1710478768, "cfa4b7573559b3b199478880c8013fa713ca81ca8754a3fd68a6d7ee6147dc5a"],
+	["86bc233e02ba3c647e356558e7252481a7769491fb46e883dd547a4ce9898fc9a1ca1b77790000000006ab5351abab51f0c1d09c37696d5c7c257788f5dff5583f4700687bcb7d4acfb48521dc953659e325fa390300000003acac5280f29523027225af03000000000963abac0065ab65acab7e59d90400000000016549dac846", "53006aac52acac", 0, 711159875, "880330ccde00991503ea598a6dfd81135c6cda9d317820352781417f89134d85"],
+	["beac155d03a853bf18cd5c490bb2a245b3b2a501a3ce5967945b0bf388fec2ba9f04c03d68030000000012fe96283aec4d3aafed8f888b0f1534bd903f9cd1af86a7e64006a2fa0d2d30711af770010000000163ffffffffd963a19d19a292104b9021c535d3e302925543fb3b5ed39fb2124ee23a9db00302000000056500ac63acffffffff01ad67f503000000000300ac5189f78db2", "53536a636500", 2, 748992863, "bde3dd0575164d7ece3b5783ce0783ffddb7df98f178fe6468683230314f285a"],
+	["81dab34a039c9e225ba8ef421ec8e0e9d46b5172e892058a9ade579fe0eb239f7d9c97d45b0300000009ac65655351ab526363ffffffff10c0faaf7f597fc8b00bbc67c3fd4c6b70ca6b22718d15946bf6b032e62dae570000000005536a00ab6a02cddec3acf985bbe62c96fccf17012a87026ed63fc6756fa39e286eb4c2dd79b59d37400300000002516affffffff04f18b8d03000000000753abab5152636564411c02000000000400ab6300e965750300000000001bd2cf02000000000565ab526aab00000000", "006551ab", 0, -1488174485, "a3d65a8cd0c1eea8558d01396b929520a2221c29d9f25f29035b8abae874447f"],
+	["489ebbf10478e260ba88c0168bd7509a651b36aaee983e400c7063da39c93bf28100011f280100000004abab63ab2fc856f05f59b257a4445253e0d91b6dffe32302d520ac8e7f6f2467f7f6b4b65f2f59e903000000096353abacab6351656affffffff0122d9480db6c45a2c6fd68b7bc57246edffbf6330c39ccd36aa3aa45ec108fc030000000265ab9a7e78a69aadd6b030b12602dff0739bbc346b466c7c0129b34f50ae1f61e634e11e9f3d0000000006516a53525100ffffffff011271070000000000086563ab6353536352c4dd0e2c", "", 0, -293358504, "4eba3055bc2b58765593ec6e11775cea4b6493d8f785e28d01e2d5470ea71575"],
+	["6911195d04f449e8eade3bc49fd09b6fb4b7b7ec86529918b8593a9f6c34c2f2d301ec378b000000000263ab49162266af054643505b572c24ff6f8e4c920e601b23b3c42095881857d00caf56b28acd030000000565525200ac3ac4d24cb59ee8cfec0950312dcdcc14d1b360ab343e834004a5628d629642422f3c5acc02000000035100accf99b663e3c74787aba1272129a34130668a877cc6516bfb7574af9fa6d07f9b4197303400000000085351ab5152635252ffffffff042b3c95000000000000ff92330200000000046a5252ab884a2402000000000853530065520063000d78be03000000000953abab52ab53ac65aba72cb34b", "6a", 2, -637739405, "6b80d74eb0e7ee59d14f06f30ba7d72a48d3a8ff2d68d3b99e770dec23e9284f"],
+	["746347cf03faa548f4c0b9d2bd96504d2e780292730f690bf0475b188493fb67ca58dcca4f0000000002005336e3521bfb94c254058e852a32fc4cf50d99f9cc7215f7c632b251922104f638aa0b9d080100000008656aac5351635251ffffffff4da22a678bb5bb3ad1a29f97f6f7e5b5de11bb80bcf2f7bb96b67b9f1ac44d09030000000365ababffffffff036f02b30000000000076353ab6aac63ac50b72a050000000002acaba8abf804000000000663006a6a6353797eb999", "acac5100", 1, -1484493812, "164c32a263f357e385bd744619b91c3f9e3ce6c256d6a827d6defcbdff38fa75"],
+	["e17149010239dd33f847bf1f57896db60e955117d8cf013e7553fae6baa9acd3d0f1412ad90200000006516500516500cb7b32a8a67d58dddfb6ceb5897e75ef1c1ff812d8cd73875856487826dec4a4e2d2422a0100000004ac525365196dbb69039229270400000000070000535351636a8b7596020000000006ab51ac52655131e99d040000000003516551ee437f5c", "ac656a53", 1, 1102662601, "8858bb47a042243f369f27d9ab4a9cd6216adeac1c1ac413ed0890e46f23d3f3"],
+	["144971940223597a2d1dec49c7d4ec557e4f4bd207428618bafa3c96c411752d494249e1fb0100000004526a5151ffffffff340a545b1080d4f7e2225ff1c9831f283a7d4ca4d3d0a29d12e07d86d6826f7f0200000003006553ffffffff03c36965000000000000dfa9af00000000000451636aac7f7d140300000000016300000000", "", 1, -108117779, "c84fcaf9d779df736a26cc3cabd04d0e61150d4d5472dd5358d6626e610be57f"],
+	["b11b6752044e650b9c4744fb9c930819227d2ac4040d8c91a133080e090b042a142e93906e0000000003650053ffffffff6b9ce7e29550d3c1676b702e5e1537567354b002c8b7bb3d3535e63ad03b50ea01000000055100516300fffffffffcf7b252fea3ad5a108af3640a9bc2cd724a7a3ce22a760fba95496e88e2f2e801000000036a00ac7c58df5efba193d33d9549547f6ca839f93e14fa0e111f780c28c60cc938f785b363941b000000000863ab51516552ac5265e51fcd0308e9830400000000036a00abab72190300000000016a63d0710000000000050051ab6a6300000000", "53005165ac51ab65", 0, 229563932, "e562579d1a2b10d1c5e45c06513456002a6bec157d7eb42511d30b118103c052"],
+	["2aee6b9a02172a8288e02fac654520c9dd9ab93cf514d73163701f4788b4caeeb9297d2e250300000004ab6363008fb36695528d7482710ea2926412f877a3b20acae31e9d3091406bfa6b62ebf9d9d2a6470100000009535165536a63520065ffffffff03f7b560050000000003acab6a9a8338050000000000206ce90000000000056552516a5100000000", "5252", 1, -1102319963, "fa4676c374ae3a417124b4c970d1ed3319dc3ac91fb36efca1aa9ed981a8aa1b"],
+	["9554595203ad5d687f34474685425c1919e3d2cd05cf2dac89d5f33cd3963e5bb43f8706480100000000ffffffff9de2539c2fe3000d59afbd376cb46cefa8bd01dbc43938ff6089b63d68acdc2b02000000096553655251536a6500fffffffff9695e4016cd4dfeb5f7dadf00968e6a409ef048f81922cec231efed4ac78f5d010000000763abab6a5365006caaf0070162cc640200000000045163ab5100000000", "", 0, -1105256289, "e8e10ed162b1a43bfd23bd06b74a6c2f138b8dc1ab094ffb2fa11d5b22869bee"],
+	["04f51f2a0484cba53d63de1cb0efdcb222999cdf2dd9d19b3542a896ca96e23a643dfc45f00200000007acac53510063002b091fd0bfc0cfb386edf7b9e694f1927d7a3cf4e1d2ce937c1e01610313729ef6419ae7030000000165a3372a913c59b8b3da458335dc1714805c0db98992fd0d93f16a7f28c55dc747fe66a5b503000000095351ab65ab52536351ffffffff5650b318b3e236802a4e41ed9bc0a19c32b7aa3f9b2cda1178f84499963a0cde000000000165ffffffff0383954f04000000000553ac536363a8fc90030000000000a2e315000000000005acab00ab5100000000", "0053", 2, -1424653648, "a5bc0356f56b2b41a2314ec05bee7b91ef57f1074bcd2efc4da442222269d1a3"],
+	["5e4fab42024a27f0544fe11abc781f46596f75086730be9d16ce948b04cc36f86db7ad50fd01000000026a00613330f4916285b5305cc2d3de6f0293946aa6362fc087727e5203e558c676b314ef8dd401000000001af590d202ba496f040000000001009e3c9604000000000351ac51943d64d3", "51acabab5100ab52", 1, -129301207, "556c3f90aa81f9b4df5b92a23399fe6432cf8fecf7bba66fd8fdb0246440036c"],
+	["a115284704b88b45a5f060af429a3a8eab10b26b7c15ed421258f5320fa22f4882817d6c2b0300000003005300ffffffff4162f4d738e973e5d26991452769b2e1be4b2b5b7e8cbeab79b9cf9df2882c040000000006636aac63ac5194abc8aa22f8ddc8a7ab102a58e39671683d1891799d19bd1308d24ea6d365e571172f1e030000000700515352515153ffffffff4da7ad75ce6d8541acbb0226e9818a1784e9c97c54b7d1ff82f791df1c6578f60000000000ffffffff01b1f265040000000009ab0051ac656a516a5300000000", "51abab6352535265", 0, -1269106800, "0ef7b6e87c782fa33fe109aab157a2d9cddc4472864f629510a1c92fa1fe7fc1"],
+	["f3f771ae02939752bfe309d6c652c0d271b7cab14107e98032f269d92b2a8c8853ab057da8010000000563ab6a6365670c305c38f458e30a7c0ab45ee9abd9a8dc03bae1860f965ffced879cb2e5d0bb156821020000000153ffffffff025dc619050000000002ac51ec0d250100000000076a5200636a6363333aecd8", "650053ac515100ab", 1, 1812404608, "a7aa34bf8a5644f03c6dd8801f9b15ba2e07e07256dbf1e02dad59f0d3e17ea9"],
+	["fd3e267203ae7d6d3975e738ca84f12540229bb237dd228d5f688e9d5ba53fce4302b0334d01000000026353ffffffff602a3ab75af7aa951d93093e345ef0037a2863f3f580a9b1a575fffe68e677450300000000239e476d1e8f81e8b6313880d8a49b27c1b00af467f29756e76f675f084a5676539636ab030000000765ab6351acac52d9217747044d773204000000000752ac51526353acc33e45050000000005516500005115d889040000000004ab5163510cbbbd0200000000016500000000", "65ac526aac6a53ab52", 2, -886179388, "bc46f3f83058ddf5bebd9e1f2c117a673847c4dc5e31cfb24bac91adf30877cf"],
+	["f380ae23033646af5dfc186f6599098015139e961919aea28502ea2d69474413d94a555ea2000000000853635265abacac5314da394b99b07733341ddba9e86022637be3b76492992fb0f58f23c915098979250a96620300000003ab6300ffffffff4bb6d1c0a0d84eac7f770d3ad0fdc5369ae42a21bbe4c06e0b5060d5990776220300000000ffffffff0486fd70020000000007ac6500635252acf3fd72010000000005656a6a6551212de90500000000096365006a63635153000fa33100000000000600535151656300000000", "ab52", 2, -740890152, "f804fc4d81f039009ed1f2cccb5c91da797543f235ac71b214c20e763a6d86d7"],
+	["5c45d09801bb4d8e7679d857b86b97697472d514f8b76d862460e7421e8617b15a2df217c6010000000863acacab6565006affffffff01156dbc03000000000952ac63516551ac6aac00000000", "6aabac", 0, 1310125891, "270445ab77258ced2e5e22a6d0d8c36ac7c30fff9beefa4b3e981867b03fa0ad"],
+	["4ecc6bde030ca0f83c0ed3d4b777f94c0c88708c6c933fe1df6874f296d425cac95355c23d0000000006ac6a51536a52f286a0969d6170e20f2a8000193807f5bc556770e9d82341ef8e17b0035eace89c76edd50200000007ac65525100656affffffff5bade6e462fac1927f078d69d3a981f5b4c1e59311a38efcb9a910aa436afaa80000000007ac6a006352ab52ffffffff0331e58902000000000763ac53636352abb8b3ca000000000001637a1d26040000000009535263ac6a5352ab655ae34a39", "6a65ab", 2, 2142728517, "4a3415eb1677ae4e0c939644a4cfd5dc6299780b55cd0dc735967057b6b1526a"],
+	["a59484b501eb50114be0fc79e72ab9bc9f4a5f7acdf274a56d6b68684eb68cf8b07ec5d1c2000000000765abab00ab00639e09aa940141e3530200000000046500ac6500000000", "00516565ab", 0, -1561622405, "d60bbadd2cc0674100baa08d0e0493ee4248f0304b3eb778da942041f503a896"],
+	["53dc1a88046531c7b57a35f4d9adf101d068bf8d63fbbedaf4741dba8bc5e92c8725def571030000000453655251fcdf116a226b3ec240739c4c7493800e4edfe67275234e371a227721eac43d3d9ecaf1b50300000003ac0052ffffffff2c9279ffeea4718d167e9499bd067600715c14484e373ef93ae4a31d2f5671ab0000000009516553ac636a6a65001977752eeba95a8f16b88c571a459c2f2a204e23d48cc7090e4f4cc35846ca7fc0a455ce00000000055165ac0063188143f80205972902000000000765ac63ac516353c7b6a50000000000036a510000000000", "655351536a", 0, 103806788, "b276584d3514e5b4e058167c41dc02915b9d97f6795936a51f40e894ed8508bc"],
+	["53f8959f01ddb36afdcd20167edcbb75a63d18654fdcf10bc0004c761ab450fe236d79cb2702000000065151650063653435003a033a5e34050000000009ac52516a630000516ab86db3030000000002006344ac090500000000046363ab00f3644537", "5263abab63ac656353", 0, -218513553, "f1f2a489682e42a6fc20025dfc89584d17f150b2d7ae3ddedd2bf43d5e24f37f"],
+	["5a06cb4602dcfc85f49b8d14513f33c48f67146f2ee44959bbca092788e6823b2719f3160b0200000001ab3c013f2518035b9ea635f9a1c74ec1a3fb7496a160f46aae2e09bfc5cd5111a0f20969e003000000015158c89ab7049f20d6010000000008ac6a52abac53515349765e00000000000300ab638292630100000000045351ab0086da09010000000006656a6365525300000000", "526a63", 1, 1502936586, "bdfaff8a4e775379c5dc26e024968efa805f923de53fa8272dd53ec582afa0c5"],
+	["ca9d84fa0129011e1bf27d7cb71819650b59fb292b053d625c6f02b0339249b498ff7fd4b601000000025352ffffffff032173a0040000000008525253abab5152639473bb030000000009005153526a53535151d085bd0000000000086a5365ab5165655300000000", "005152ac51", 0, 580353445, "c629d93b02037f40aa110e46d903edb34107f64806aa0c418d435926feef68b8"],
+	["e3cdbfb4014d90ae6a4401e85f7ac717adc2c035858bf6ff48979dd399d155bce1f150daea0300000002ac51a67a0d39017f6c71040000000005535200535200000000", "", 0, -1899950911, "c1c7df8206e661d593f6455db1d61a364a249407f88e99ecad05346e495b38d7"],
+	["b2b6b9ab0283d9d73eeae3d847f41439cd88279c166aa805e44f8243adeb3b09e584efb1df00000000026300ffffffff7dfe653bd67ca094f8dab51007c6adaced09de2af745e175b9714ca1f5c68d050000000003ac6500aa8e596903fd3f3204000000000553ac6a6a533a2e210500000000075253acabab526392d0ee020000000008520065635200ab5200000000", "65acacac65005365", 0, 28298553, "39c2aaa2496212b3ab120ab7d7f37c5e852bfe38d20f5226413a2268663eeae8"],
+	["f30c5c3d01a6edb9e10fafaf7e85db14e7fec558b9dca4a80b05d7c3a2944d282c5018f4680200000003005263ffffffff04aac3530300000000026551bc2419010000000009005163acab6a5100658e7085050000000000c5e4ec050000000007656a6a635365ab2d8e8882", "abac53ab005251ac52", 0, -490287546, "877e347ec7487497769e2581142276d1a8d813b652e4483cf9cc993d16354417"],
+	["4314339e01de40faabcb1b970245a7f19eedbc17c507dac86cf986c2973715035cf95736ae0200000007abababababab65bde67b900151510b04000000000853ac00655200535300000000", "52", 0, 399070095, "47585dc25469d04ff3a60939d0a03779e3e81a411bf0ca18b91bb925ebd30718"],
+	["2d4cf4e9031b3e175b2ff18cd933151379d9cfac4713d8bd0e63b70bd4a92277aa7af901ab000000000565515353abffffffff557666c7f3be9cdecdad44c3df206eb63a2da4ed1f159d21193882a9f0340081020000000963ab53ab5252ac63abffffffff8a8c897bdb87e93886aad5ded9d82a13101d5476554386373646ca5e23612e450300000009006a526552abab6a635ac03fc00198bb02040000000009525100526a6563636a1d052834", "ab52ac00acac6a", 0, -1469882480, "09ed6563a454814ab7e3b4c28d56d8751162b77df1825b37ba66c6147750b2a3"],
+	["f063171b03e1830fdc1d685a30a377537363ccafdc68b42bf2e3acb908dac61ee24b37595c020000000765ac5100ab6aacf447bc8e037b89d6cadd62d960cc442d5ced901d188867b5122b42a862929ce45e7b628d010000000253aba009a1ba42b00f1490b0b857052820976c675f335491cda838fb7934d5eea0257684a2a202000000001e83cf2401a7f777030000000008ab6553526a53526a00000000", "", 2, 1984790332, "c19caada8e71535e29a86fa29cfd9b74a0c7412003fc722a121005e461e01636"],
+	["cf7bdc250249e22cbe23baf6b648328d31773ea0e771b3b76a48b4748d7fbd390e88a004d30000000003ac536a4ab8cce0e097136c90b2037f231b7fde2063017facd40ed4e5896da7ad00e9c71dd70ae600000000096a0063516352525365ffffffff01b71e3e00000000000300536a00000000", "", 1, 546970113, "6a815ba155270af102322c882f26d22da11c5330a751f520807936b320b9af5d"],
+	["ac7a125a0269d35f5dbdab9948c48674616e7507413cd10e1acebeaf85b369cd8c88301b7c030000000963656aac6a530053abffffffffed94c39a582e1a46ce4c6bffda2ccdb16cda485f3a0d94b06206066da12aecfe010000000752abab63536363ef71dcfb02ee07fa0400000000016a6908c802000000000751656a6551abac688c2c2d", "6a6351526551", 0, 858400684, "552ff97d7924f51cda6d1b94be53483153ef725cc0a3a107adbef220c753f9a6"],
+	["3a1f454a03a4591e46cf1f7605a3a130b631bf4dfd81bd2443dc4fac1e0a224e74112884fe0000000005516aac6a53a87e78b55548601ffc941f91d75eab263aa79cd498c88c37fdf275a64feff89fc1710efe03000000016a39d7ef6f2a52c00378b4f8f8301853b61c54792c0f1c4e2cd18a08cb97a7668caa008d970200000002656affffffff017642b20100000000096a63535253abac6a6528271998", "51", 2, 1459585400, "e9a7f21fc2d38be7be47095fbc8f1bf8923660aa4d71df6d797ae0ba5ca4d5b0"],
+	["f59366cc0114c2a18e6bd1347ed9470f2522284e9e835dd5c5f7ef243639ebea95d9b232b6020000000153474b62eb045c00170500000000096352ab516352ab5200038a520400000000086aab5253656a63005b968904000000000963536353ac0053635387106002000000000000000000", "ab52526300ab51", 0, 1834116153, "cdf51f6e3a9dc2be5a59ea4c00f5aac1e1426a5202c325e6cf2567d07d8d8de4"],
+	["6269e0fa0173e76e89657ca495913f1b86af5b8f1c1586bcd6c960aede9bc759718dfd5044000000000352ac530e2c7bd90219849b000000000007ab00ab6a53006319f281000000000007ab00515165ac5200000000", "6a", 0, -2039568300, "62094f98234a05bf1b9c7078c5275ed085656856fb5bdfd1b48090e86b53dd85"],
+	["eb2bc00604815b9ced1c604960d54beea4a3a74b5c0035d4a8b6bfec5d0c9108f143c0e99a0000000000ffffffff22645b6e8da5f11d90e5130fd0a0df8cf79829b2647957471d881c2372c527d8010000000263acffffffff1179dbaf17404109f706ae27ad7ba61e860346f63f0c81cb235d2b05d14f2c1003000000025300264cb23aaffdc4d6fa8ec0bb94eff3a2e50a83418a8e9473a16aaa4ef8b855625ed77ef40100000003ac51acf8414ad404dd328901000000000652526500006ab6261c000000000002526a72a4c9020000000006ac526500656586d2e7000000000006656aac00ac5279cd8908", "51", 1, -399279379, "d37532e7b2b8e7db5c7c534197600397ebcc15a750e3af07a3e2d2e4f84b024f"],
+	["dc9fe6a8038b84209bbdae5d848e8c040433237f415437592907aa798bf30d9dbbddf0ff85010000000153ffffffff23269a7ea29fcf788db483b8d4c4b35669e582608644259e950ce152b0fa6e050000000003acababffffffff65de94857897ae9ea3aa0b938ba6e5adf374d48469922d2b36dbb83d3b8c8261010000000452ac5200ffffffff02856e9b0300000000026a51980c8e02000000000365ab63d2648db4", "00ab0051ac526565", 2, 1562581941, "5cef9d8e18a2d5a70448f17b465d411a19dab78f0ddf1672ffd518b188f52433"],
+	["eba8b0de04ac276293c272d0d3636e81400b1aaa60db5f11561480592f99e6f6fa13ad387002000000070053acab536563bebb23d66fd17d98271b182019864a90e60a54f5a615e40b643a54f8408fa8512cfac927030000000963ac6a6aabac65ababffffffff890a72192bc01255058314f376bab1dc72b5fea104c154a15d6faee75dfa5dba020000000100592b3559b0085387ac7575c05b29b1f35d9a2c26a0c27903cc0f43e7e6e37d5a60d8305a030000000252abffffffff0126518f05000000000000000000", "005300635252635351", 1, 664344756, "26dc2cba4bd5334e5c0b3a520b44cc1640c6b923d10e576062f1197171724097"],
+	["91bd040802c92f6fe97411b159df2cd60fb9571764b001f31657f2d616964637605875c2a901000000055263006a65ffffffff3651df372645f50cf4e32fdf6e61c766e912e16335db2b40c5d52fe89eefe7cd00000000040065ab65ffffffff03ca8625030000000009ab51ac63530052ab52c6bf14020000000006ab00ab52005167d270000000000007ab53525351636a00000000", "5151ab63005252ac", 1, 1983087664, "3e5aa0200248d8d86ede3b315ca1b857018b89184a4bd023bd88ab12e499f6e1"],
+	["185cda1a01ecf7a8a8c28466725b60431545fc7a3367ab68e34d486e8ea85ee3128e0d8384000000000465ac63abec88b7bb031c56eb04000000000965636a51005252006a7c78d5040000000007acac63abac51ac3024a40500000000086300526a51abac51464c0e8c", "0065535265515352", 0, 1594558917, "b5280b9610c0625a65b36a8c2402a95019a7bbb9dd3de77f7c3cb1d82c3263ba"],
+	["a9531f07034091668b65fea8b1a79700d586ac9e2f42ca0455a26abe41f9e1805d009a0f5702000000096365516365ac5263ab3619bac643a9e28ee47855118cf80c3a74531cdf198835d206d0fe41804e325a4f9f105e03000000016a58e3ab0d46375d98994daf0fa7c600d2bb4669e726fca0e3a3f21ea0d9e777396740328f0100000008636a5363ab526a538d3ea7700304cb66030000000007515163ab52ab510184030500000000085353636565ac0051d9cff402000000000751ab52ab5352abf0e36254", "ab5353ac5365acab", 2, 1633101834, "04c9ef72f33668ca449c0415becf62cc0b8e0c75f9c8813852d42a58acf107c8"],
+	["6b5ecc7903fe0ba37ea551df92a59e12bad0a3065846ba69179a8f4a741a2b4fcf679aac810200000004535263529a3d343293b99ab425e7ef8529549d84f480bcd92472bab972ea380a302128ae14dfcd0200000000025163ffffffff24636e4545cab9bf87009119b7fc3ec4d5ee9e206b90f35d1df8a563b6cd097a010000000852abac53005153abc64467860406e832020000000009526300006a53ac6352ac1395010000000002ac53b117f300000000000863655351acab00651edf02030000000008ab51ac6353535252628ef71d", "ab63ab6a52ac526563", 2, -1559697626, "8f07ece7d65e509f1e0780584ef8d271c1c61a13b10335d5faafc7afc8b5b8ec"],
+	["92c9fb780138abc472e589d5b59489303f234acc838ca66ffcdf0164517a8679bb622a4267020000000153468e373d04de03fa020000000009ac006a5265ab5163006af649050000000007515153006a00658ceb59030000000001ac36afa0020000000009ab53006351ab51000000000000", "6a", 0, 2059357502, "e2358dfb51831ee81d7b0bc602a65287d6cd2dbfacf55106e2bf597e22a4b573"],
+	["6f62138301436f33a00b84a26a0457ccbfc0f82403288b9cbae39986b34357cb2ff9b889b302000000045253655335a7ff6701bac9960400000000086552ab656352635200000000", "6aac51", 0, 1444414211, "502a2435fd02898d2ff3ab08a3c19078414b32ec9b73d64a944834efc9dae10c"],
+	["9981143a040a88c2484ac3abe053849e72d04862120f424f373753161997dd40505dcb4783030000000700536365536565a2e10da3f4b1c1ad049d97b33f0ae0ea48c5d7c30cc8810e144ad93be97789706a5ead180100000003636a00ffffffffbdcbac84c4bcc87f03d0ad83fbe13b369d7e42ddb3aecf40870a37e814ad8bb5010000000963536a5100636a53abffffffff883609905a80e34202101544f69b58a0b4576fb7391e12a769f890eef90ffb72020000000651656352526affffffff04243660000000000004ab5352534a9ce001000000000863656363ab6a53652df19d030000000003ac65acedc51700000000000000000000", "ac6300acac", 2, 293672388, "7ba99b289c04718a7283f150d831175ed6303081e191a0608ea81f78926c5bdf"],
+	["a2bb630b01989bc5d643f2da4fb9b55c0cdf846ba06d1dbe372893024dbbe5b9b8a1900af802000000055265ac63aca7a68d2f04916c74010000000003abac007077f0040000000001007d4127010000000005ac516aac000f31e8030000000000571079c9", "65ab0051ac", 0, -1103627693, "92d53b4390262e6b288e8a32e0cfc36cd5adfdfabfe96c7bfd4a19d65e233761"],
+	["49f7d0b6037bba276e910ad3cd74966c7b3bc197ffbcfefd6108d6587006947e97789835ea0300000008526a52006a650053ffffffff8d7b6c07cd10f4c4010eac7946f61aff7fb5f3920bdf3467e939e58a1d4100ab03000000076aac63ac535351ffffffff8f48c3ba2d52ad67fbcdc90d8778f3c8a3894e3c35b9730562d7176b81af23c80100000003ab5265ffffffff0301e3ef0300000000046a525353e899ac0500000000075153ab6a65abac259bea0400000000007b739972", "53516aacac6aac", 1, 955403557, "5d366a7f4346ae18aeb7c9fc4dab5af71173184aa20ed22fcb4ea8511ad25449"],
+	["58a4fed801fbd8d92db9dfcb2e26b6ff10b120204243fee954d7dcb3b4b9b53380e7bb8fb60100000003006351ffffffff02a0795b050000000006536351ac6aac2718d00200000000075151acabac515354d21ba1", "005363515351", 0, -1322430665, "bbee941bbad950424bf40e3623457db47f60ed29deaa43c99dec702317cb3326"],
+	["32765a0b02e455793d9ce530e9f6a44bcbc612e893a875b5da61d822dc56d8245166c398b403000000085353abac6300006a6bdee2a78d0d0b6a5ea666eed70b9bfea99d1d612ba3878f615c4da10d4a521cba27155002000000035363abffffffff043cd42401000000000551656a53653685320100000000030000511881bc0500000000065165abab636a20169f010000000007acab656aac63acdb0706a8", "65ac53ab53", 0, 1936499176, "5c5a9c3a5de7dc7a82bc171c9d3505913b8bcc450bc8b2d11772c1a1d781210b"],
+	["17fad0d303da0d764fedf9f2887a91ea625331b28704940f41e39adf3903d8e75683ef6d46020000000151ffffffffff376eea4e880bcf0f03d33999104aafed2b3daf4907950bb06496af6b51720a020000000900636a63525253525196521684f3b08497bad2c660b00b43a6a517edc58217876eb5e478aa3b5fda0f29ee1bea00000000046aacab6affffffff03dde8e2050000000007ac5365ac51516a14772e000000000005630000abacbbb360010000000006ab5251ab656a50f180f0", "0053", 0, -1043701251, "a3bdf8771c8990971bff9b4e7d59b7829b067ed0b8d3ac1ec203429811384668"],
+	["236c32850300045e292c84ede2b9ab5733ba08315a2bb09ab234c4b4e8894808edbdac0d3b020000000653635363abacffffffffd3f696bb31fdd18a72f3fc2bb9ae54b416a253fc37c1a0f0180b52d35bad49440100000004650053abffffffffa85c75a2406d82a93b12e555b66641c1896a4e83ae41ef1038218311e38ace060200000006abab006a51ac104b5e6701e2842c04000000000800630051ac0000ab00000000", "ab63ac6a516a", 1, -1709887524, "8c29ea8ef60c5a927fccdba8ea385db6b6b84d98e891db45f5d4ee3148d3f5a7"],
+	["b78d5fd601345f3100af494cdf447e7d4076179f940035b0ebe8962587d4d0c9c6c9fc34ee0300000003516a6affffffff03dc5c890100000000085353ac53ac6a52534ac941040000000007ac63656a51ab51d4266b0100000000036aacac70731f2d", "005351ab0053", 0, -1789071265, "d5f1c1cb35956a5711d67bfb4cedbc67e77c089b912d688ad440ff735adb390d"],
+	["5a2257df03554550b774e677f348939b37f8e765a212e566ce6b60b4ea8fed4c9504b7f7d1000000000653655265ab5258b67bb931df15b041177cf9599b0604160b79e30f3d7a594e7826bae2c29700f6d8f8f40300000005515300ac6a159cf8808a41f504eb5c2e0e8a9279f3801a5b5d7bc6a70515fbf1c5edc875bb4c9ffac500000000050063510052ffffffff0422a90105000000000965006a650000516a006417d2020000000006526363ab00524d969d0100000000035153acc4f077040000000005ac5200636500000000", "6a52", 1, -1482463464, "37b794b05d0687c9b93d5917ab068f6b2f0e38406ff04e7154d104fc1fb14cdc"],
+	["e0032ad601269154b3fa72d3888a3151da0aed32fb2e1a15b3ae7bee57c3ddcffff76a1321010000000100110d93ae03f5bd080100000000075263516a6551002871e60100000000046a005252eaa753040000000004ab6aab526e325c71", "630052", 0, -1857873018, "ea117348e94de86381bb8ad1c7f93b8c623f0272104341701bb54e6cb433596c"],
+	["014b2a5304d46764817aca180dca50f5ab25f2e0d5749f21bb74a2f8bf6b8b7b3fa8189cb7030000000965ac5165ab6a51ac6360ecd91e8abc7e700a4c36c1a708a494c94bb20cbe695c408543146566ab22be43beae9103000000045163ab00ffffffffffa48066012829629a9ec06ccd4905a05df0e2b745b966f6a269c9c8e13451fc00000000026565ffffffffc40ccadc21e65fe8a4b1e072f4994738ccaf4881ae6fede2a2844d7da4d199ab02000000065152ab536aabffffffff01b6e054030000000004515352ab3e063432", "", 0, 1056459916, "a7aff48f3b8aeb7a4bfe2e6017c80a84168487a69b69e46681e0d0d8e63a84b6"],
+	["c4ef04c103c5dde65410fced19bf6a569549ecf01ceb0db4867db11f2a3a3eef0320c9e8e001000000085100536a53516aabffffffff2a0354fa5bd96f1e28835ffe30f52e19bd7d5150c687d255021a6bec03cf4cfd03000000056a006300514900c5b01d3d4ae1b97370ff1155b9dd0510e198d266c356d6168109c54c11b4c283dca00300000002ababffffffff02e19e3003000000000451655351fa5c0003000000000163ef1fc64b", "51636a51ab630065", 1, -1754709177, "0a281172d306b6a32e166e6fb2a2cc52c505c5d60ea448e9ba7029aa0a2211e1"],
+	["29083fe00398bd2bb76ceb178f22c51b49b5c029336a51357442ed1bac35b67e1ae6fdf13100000000066a6500acab51ffffffffe4ca45c9dc84fd2c9c47c7281575c2ba4bf33b0b45c7eca8a2a483f9e3ebe4b3010000000200abffffffffdf47ad2b8c263fafb1e3908158b18146357c3a6e0832f718cd464518a219d18303000000096352ac656351ac0052daddfb3b0231c36f00000000000400526a5275c7e0020000000001ab00000000", "acab536aac52", 2, 300802386, "82ebc07b16cff0077e9c1a279373185b3494e39d08fd3194aae6a4a019377509"],
+	["1201ab5d04f89f07c0077abd009762e59db4bb0d86048383ba9e1dad2c9c2ad96ef660e6d00200000007ab6a65ac5200652466fa5143ab13d55886b6cdc3d0f226f47ec1c3020c1c6e32602cd3428aceab544ef43e00000000086a6a6a526a6a5263ffffffffd5be0b0be13ab75001243749c839d779716f46687e2e9978bd6c9e2fe457ee48020000000365abab1e1bac0f72005cf638f71a3df2e3bbc0fa35bf00f32d9c7dc9c39a5e8909f7d53170c8ae0200000008ab6a51516363516affffffff02f0a6210500000000036300ac867356010000000009acab65ac6353536a659356d367", "ac53535252", 0, 917543338, "418acc156c2bc76a5d7baa58db29f1b4cf6c266c9222ed167ef5b4d47f0e0f41"],
+	["344fa11e01c19c4dd232c77742f0dd0aeb3695f18f76da627628741d0ee362b0ea1fb3a2180200000007635151005100529bab25af01937c1f0500000000055153ab53656e7630af", "6351005163ac51", 0, -629732125, "228ca52a0a376fe0527a61cfa8da6d7baf87486bba92d49dfd3899cac8a1034f"],
+	["b2fda1950191358a2b855f5626a0ebc830ab625bea7480f09f9cd3b388102e35c0f303124c030000000565ac65ab53ffffffff03f9c5ec04000000000765ab51516551650e2b9f0500000000045365525284e8f6040000000001ac00000000", "ac51655253", 0, 1433027632, "d2fa7e13c34cecda5105156bd2424c9b84ee0a07162642b0706f83243ff811a8"],
+	["a4a6bbd201aa5d882957ac94f2c74d4747ae32d69fdc765add4acc2b68abd1bdb8ee333d6e0300000008516a6552515152abffffffff02c353cb040000000007ac6351ab51536588bd320500000000066552525253ac00000000", "", 0, 1702060459, "499da7d74032388f820645191ac3c8d20f9dba8e8ded7fa3a5401ea2942392a1"],
+	["584e8d6c035a6b2f9dac2791b980a485994bf38e876d9dda9b77ad156eee02fa39e19224a60300000003ab636529db326cc8686a339b79ab6b6e82794a18e0aabc19d9ad13f31dee9d7aad8eff38288588020000000452530052ffffffff09a41f07755c16cea1c7e193c765807d18cadddca6ec1c2ed7f5dcdca99e90e80000000001acffffffff01cba62305000000000451ac63acccdf1f67", "ab536a6363", 2, -27393461, "1125645b49202dca2df2d76dae51877387903a096a9d3f66b5ac80e042c95788"],
+	["83a583d204d926f2ee587a83dd526cf1e25a44bb668e45370798f91a2907d184f7cddcbbc7030000000700ab6565536a539f71d3776300dffdfa0cdd1c3784c9a1f773e34041ca400193612341a9c42df64e3f550e01000000050052515251ffffffff52dab2034ab0648553a1bb8fc4e924b2c89ed97c18dfc8a63e248b454035564b01000000015139ab54708c7d4d2c2886290f08a5221cf69592a810fd1979d7b63d35c271961e710424fd0300000005ac65ac5251ffffffff01168f7c030000000000a85e5fb0", "6a536353656a00", 0, 179595345, "5350a31ac954a0b49931239d0ecafbf34d035a537fd0c545816b8fdc355e9961"],
+	["ffd35d51042f290108fcb6ea49a560ba0a6560f9181da7453a55dfdbdfe672dc800b39e7320200000006630065516a65f2166db2e3827f44457e86dddfd27a8af3a19074e216348daa0204717d61825f198ec0030100000006ab51abab00abffffffffdf41807adb7dff7db9f14d95fd6dc4e65f8402c002d009a3f1ddedf6f4895fc8030000000500ab006a65a5a848345052f860620abd5fcd074195548ce3bd0839fa9ad8642ed80627bf43a0d47dbd010000000765ab006a656a53b38cdd6502a186da05000000000765ab00ab006a53527c0e0100000000085365ab51acacac52534bd1b1", "6a635253ac0000", 0, 1095082149, "3c05473a816621a3613f0e903faa1a1e44891dd40862b029e41fc520776350fa"],
+	["6c9a4b98013c8f1cae1b1df9f0f2de518d0c50206a0ab871603ac682155504c0e0ce946f460100000000ffffffff04e9266305000000000753535100ac6aacded39e04000000000365ac6ab93ccd010000000002515397bf3d050000000003ab636300000000", "63520052ac656353", 0, -352633155, "936eff8cdfd771be24124da87c7b24feb48da7cbc2c25fb5ba13d1a23255d902"],
+	["e01dc7f0021dc07928906b2946ca3e9ac95f14ad4026887101e2d722c26982c27dc2b59fdb0000000005ac5200516ab5a31ffadcbe74957a5a3f97d7f1475cc6423fc6dbc4f96471bd44c70cc736e7dec0d1ea020000000951636a526a52abac53ffffffff04bc2edd05000000000252ab528c7b02000000000952ac51526500525353324820040000000002005380c713000000000009630065ab00ac525252451bbb48", "53ab65ac", 0, -552384418, "69c0b30f4c630a6c878fde6ea6b74dae94f4eb3bcfbde2dc3649e1a9ada00757"],
+	["009046a1023f266d0113556d604931374d7932b4d6a7952d08fbd9c9b87cbd83f4f4c178b4030000000452ac526346e73b438c4516c60edd5488023131f07acb5f9ea1540b3e84de92f4e3c432289781ea4900000000046500655357dfd6da02baef910100000000026a007d101703000000000800516500abacac5100000000", "6aab6553ac", 0, -802456605, "f8757fbb4448ca34e0cd41b997685b37238d331e70316659a9cc9087d116169d"],
+	["df76ec0801a3fcf3d18862c5f686b878266dd5083f16cf655facab888b4cb3123b3ce5db7e01000000010010e7ac6a0233c83803000000000365ac51faf14a040000000004ac51655100000000", "6353acab", 0, 15705861, "e7d873aa079a19ec712b269a37d2670f60d8cb334c4f97e2e3fd10eeb8ee5f5e"],
+	["828fd3e0031084051ccef9cfdd97fae4d9cc50c0dae36bd22a3ff332881f17e9756c3e288e0200000004ab535363961a2ccccaf0218ec6a16ba0c1d8b5e93cfd025c95b6e72bc629ec0a3f47da7a4c396dad01000000025353ffffffff19ad28747fb32b4caf7b5dbd9b2da5a264bedb6c86d3a4805cd294ae53a86ac40200000009ab53535351ab6551abffffffff04a41650030000000005656aab6aab8331a304000000000700516365ac516a0d2a47010000000007abac516353abacdebc19040000000006ab5300636a6300000000", "51ab52ab53ac52", 0, 1866105980, "311094b4d73e31aefc77e97859ef07ca2f07a7b7e4d7def80c69d3f5d58527e5"],
+	["c4b80f850323022205b3e1582f1ed097911a81be593471a8dce93d5c3a7bded92ef6c7c1260100000002006affffffff70294d62f37c3da7c5eae5d67dce6e1b28fedd7316d03f4f48e1829f78a88ae801000000096a5200530000516351f6b7b544f7c39189d3a2106ca58ce4130605328ce7795204be592a90acd81bef517d6f170200000000ffffffff012ab8080000000000075100006365006335454c1e", "53ac6a536aacac", 0, -1124103895, "06277201504e6bf8b8c94136fad81b6e3dadacb9d4a2c21a8e10017bfa929e0e"],
+	["8ab69ed50351b47b6e04ac05e12320984a63801716739ed7a940b3429c9c9fed44d3398ad40300000006536a516a52638171ef3a46a2adb8025a4884b453889bc457d63499971307a7e834b0e76eec69c943038a0300000000ffffffff566bb96f94904ed8d43d9d44a4a6301073cef2c011bf5a12a89bedbaa03e4724030000000265acb606affd01edea38050000000008515252516aacac6300000000", "65000000006365ac53", 0, -1338942849, "7912573937824058103cb921a59a7f910a854bf2682f4116a393a2045045a8c3"],
+	["2484991e047f1cf3cfe38eab071f915fe86ebd45d111463b315217bf9481daf0e0d10902a402000000006e71a424eb1347ffa638363604c0d5eccbc90447ff371e000bf52fc743ec832851bb564a0100000001abffffffffef7d014fad3ae7927948edbbb3afe247c1bcbe7c4c8f5d6cf97c799696412612020000000851536a5353006a001dfee0d7a0dd46ada63b925709e141863f7338f34f7aebde85d39268ae21b77c3068c01d0000000008535151ab00636563ffffffff018478070200000000095200635365ac52ab5341b08cd3", "", 3, 265623923, "24cb420a53b4f8bb477f7cbb293caabfd2fc47cc400ce37dbbab07f92d3a9575"],
+	["54839ef9026f65db30fc9cfcb71f5f84d7bb3c48731ab9d63351a1b3c7bc1e7da22bbd508e0300000000442ad138f170e446d427d1f64040016032f36d8325c3b2f7a4078766bdd8fb106e52e8d20000000003656500ffffffff02219aa101000000000851ababac52ab00659646bd02000000000552acacabac24c394a5", "ac", 0, 906807497, "69264faadcd1a581f7000570a239a0a26b82f2ad40374c5b9c1f58730514de96"],
+	["5036d7080434eb4eef93efda86b9131b0b4c6a0c421e1e5feb099a28ff9dd8477728639f77030000000951516aab535152ab5391429be9cce85d9f3d358c5605cf8c3666f034af42740e94d495e28b9aaa1001ba0c87580300000008006552ab00ab006affffffffd838978e10c0c78f1cd0a0830d6815f38cdcc631408649c32a25170099669daa0000000002acab8984227e804ad268b5b367285edcdf102d382d027789250a2c0641892b480c21bf84e3fb0100000000b518041e023d8653010000000001004040fb0100000000080051ac5200636a6300000000", "52ac", 0, 366357656, "bd0e88829afa6bdc1e192bb8b2d9d14db69298a4d81d464cbd34df0302c634c6"],
+	["9ad5ccf503fa4facf6a27b538bc910cce83c118d6dfd82f3fb1b8ae364a1aff4dcefabd38f03000000096365655263ac655300807c48130c5937190a996105a69a8eba585e0bd32fadfc57d24029cbed6446d30ebc1f100100000004000053650f0ccfca1356768df7f9210cbf078a53c72e0712736d9a7a238e0115faac0ca383f219d0010000000600ab536552002799982b0221b8280000000000000c41320000000000086552ac6365636a6595f233a3", "6a5152", 2, 553208588, "f99c29a79f1d73d2a69c59abbb5798e987639e36d4c44125d8dc78a94ddcfb13"],
+	["669538a204047214ce058aed6a07ca5ad4866c821c41ac1642c7d63ed0054f84677077a84f030000000853abacab6a655353ffffffff70c2a071c115282924e3cb678b13800c1d29b6a028b3c989a598c491bc7c76c5030000000752ac52ac5163ac80420e8a6e43d39af0163271580df6b936237f15de998e9589ec39fe717553d415ac02a4030000000463635153184ad8a5a4e69a8969f71288c331aff3c2b7d1b677d2ebafad47234840454b624bf7ac1d03000000056a63abab63df38c24a02fbc63a040000000002ab535ec3dc050000000002536500000000", "635153", 3, -190399351, "9615541884dfb1feeb08073a6a6aa73ef694bc5076e52187fdf4138a369f94d9"],
+	["a7f139e502af5894be88158853b7cbea49ba08417fbbca876ca6614b5a41432be34499987b000000000765635165abac63ffffffff8b8d70e96c7f54eb70da0229b548ced438e1ca2ba5ddd648a027f72277ee1efc0100000001abffffffff044f2c4204000000000165e93f550100000000050000526a6a94550304000000000365536aadc21c0300000000016300000000", "6aacac6363ab5265ac", 1, 2143189425, "6e3f97955490d93d6a107c18d7fe402f1cada79993bb0ff0d096357261b3a724"],
+	["3b94438f0366f9f53579a9989b86a95d134256ce271da63ca7cd16f7dd5e4bffa17d35133f010000000100ffffffff1aaad0c721e06ec00d07e61a84fb6dc840b9a968002ce7e142f943f06fd143a10100000008535151ac51ab0053b68b8e9c672daf66041332163e04db3f6048534bd718e1940b3fc3811c4eef5b7a56888b01000000001d58e38c012e38e700000000000852ab53ac6365536a00000000", "ab655352", 1, -935223304, "b3b336de141d4f071313a2207b2a0c7cf54a070dd8d234a511b7f1d13e23b0c4"],
+	["e5dca8a20456de0a67e185fa6ea94085ceae478d2c15c73cb931a500db3a1b6735dd1649ec0200000005ab536aabab32d11bbdcb81361202681df06a6b824b12b5cb40bb1a672cf9af8f2a836e4d95b7839327030000000951005365ab65abacabb345085932939eef0c724adef8a57f9e1bf5813852d957c039b6a12d9c2f201ea520fb030000000009ac5352005165acac6a5efc6072f1a421dc7dc714fc6368f6d763a5d76d0278b95fc0503b9268ccfadb48213a2500000000026a53ffffffff039ee1c4020000000009ac5353ab6353535163184018000000000005655265526a9a4a8a050000000001ac00000000", "65ab53ab6a00ab6553", 2, 1902561212, "7928ae8e86c0b0cad1b2c120ea313087437974382ee6d46443ca5ac3f5878b88"],
+	["972128b904e7b673517e96e98d80c0c8ceceae76e2f5c126d63da77ffd7893fb53308bb2da0300000006ac6552ab52acffffffff4cac767c797d297c079a93d06dc8569f016b4bf7a7d79b605c526e1d36a40e2202000000095365ab636aac6a6a6a69928d2eddc836133a690cfb72ec2d3115bf50fb3b0d10708fa5d2ebb09b4810c426a1db01000000060052526300001e8e89585da7e77b2dd2e30625887f0660accdf29e53a614d23cf698e6fc8ab03310e87700000000076a520051acac6555231ddb0330ec2d03000000000200abfaf457040000000004ab6a6352bdc42400000000000153d6dd2f04", "", 0, 209234698, "4a92fec1eb03f5bd754ee9bfd70707dc4420cc13737374f4675f48529be518e4"],
+	["1fb4085b022c6cfb848f8af7ba3ba8d21bd23ffa9f0bfd181cb68bcaaf2074e66d4974a31602000000090000006a6a6500acab6c12c07d9f3dbd2d93295c3a49e3757119767097e7fd5371f7d1ba9ba32f1a67a5a426f00000000000ffffffff018fd2fc04000000000363ac5100000000", "65ab006a6aab526a", 0, 1431502299, "8b7dd0ff12ca0d8f4dbf9abf0abba00e897c2f6fd3b92c79f5f6a534e0b33b32"],
+	["5374f0c603d727f63006078bd6c3dce48bd5d0a4b6ea00a47e5832292d86af258ea0825c260000000009655353636352526a6af2221067297d42a9f8933dfe07f61a574048ff9d3a44a3535cd8eb7de79fb7c45b6f47320200000003ac006affffffff153d917c447d367e75693c5591e0abf4c94bbdd88a98ab8ad7f75bfe69a08c470200000005ac65516365ffffffff037b5b7b000000000001515dc4d904000000000004bb26010000000004536a6aac00000000", "516552516352ac", 2, 328538756, "8bb7a0129eaf4b8fc23e911c531b9b7637a21ab11a246352c6c053ff6e93fcb6"],
+	["c441132102cc82101b6f31c1025066ab089f28108c95f18fa67db179610247086350c163bd010000000651525263ab00ffffffff9b8d56b1f16746f075249b215bdb3516cbbe190fef6292c75b1ad8a8988897c3000000000751ab6553abab00ffffffff02f9078b000000000009ab0053ac51ac00ab51c0422105000000000651006563525200000000", "ac51", 0, -197051790, "55acd8293ed0be6792150a3d7ced6c5ccd153ca7daf09cee035c1b0dac92bb96"],
+	["ab82ad3b04545bd86b3bb937eb1af304d3ef1a6d1343ed809b4346cafb79b7297c09e1648202000000086351ac5200535353ffffffff95d32795bbaaf5977a81c2128a9ec0b3c7551b9b1c3d952876fcb423b2dfb9e80000000005515363acac47a7d050ec1a603627ce6cd606b3af314fa7964abcc579d92e19c7aba00cf6c3090d6d4601000000056a516551633e794768bfe39277ebc0db18b5afb5f0c8117dde9b4dfd5697e9027210eca76a9be20d63000000000700520063ab6aacffffffff01ec2ddc050000000008ac52ac65ac65ac5100000000", "536300abab", 1, -2070209841, "b362da5634f20be7267de78b545d81773d711b82fe9310f23cd0414a8280801d"],
+	["8bff9d170419fa6d556c65fa227a185fe066efc1decf8a1c490bc5cbb9f742d68da2ab7f320100000007ab000053525365a7a43a80ab9593b9e8b6130a7849603b14b5c9397a190008d89d362250c3a2257504eb810200000007acabacac00ab51ee141be418f003e75b127fd3883dbf4e8c3f6cd05ca4afcaac52edd25dd3027ae70a62a00000000008ac52526a5200536affffffffb8058f4e1d7f220a1d1fa17e96d81dfb9a304a2de4e004250c9a576963a586ae0300000005abacac5363b9bc856c039c01d804000000000951656aac53005365acb0724e00000000000565abab63acea7c7a0000000000036a00ac00000000", "6565", 1, -1349282084, "2b822737c2affeefae13451d7c9db22ff98e06490005aba57013f6b9bbc97250"],
+	["0e1633b4041c50f656e882a53fde964e7f0c853b0ada0964fc89ae124a2b7ffc5bc97ea6230100000006ac6aacacabacffffffff2e35f4dfcad2d53ea1c8ada8041d13ea6c65880860d96a14835b025f76b1fbd9000000000351515121270867ef6bf63a91adbaf790a43465c61a096acc5a776b8e5215d4e5cd1492e611f761000000000600ac6aab5265ffffffff63b5fc39bcac83ca80ac36124abafc5caee608f9f63a12479b68473bd4bae769000000000965ac52acac5263acabffffffff0163153e020000000008ab005165ab65515300000000", "6a6aac00", 0, -968477862, "20732d5073805419f275c53784e78db45e53332ee618a9fcf60a3417a6e2ca69"],
+	["2b052c24022369e956a8d318e38780ef73b487ba6a8f674a56bdb80a9a63634c6110fb5154010000000251acffffffff48fe138fb7fdaa014d67044bc05940f4127e70c113c6744fbd13f8d51d45143e01000000005710db3804e01aa9030000000008acac6a516a5152abfd55aa01000000000751ab510000ac636d6026010000000000b97da9000000000000fddf3b53", "006552", 0, 595461670, "685d67d84755906d67a007a7d4fa311519467b9bdc6a351913246a41e082a29f"],
+	["073bc856015245f03b2ea2da62ccedc44ecb99e4250c7042f596bcb23b294c9dc92cfceb6b02000000095163abab52abab636afe292fb303b7c3f001000000000352636af3c49502000000000400ac6a535851850100000000066aac6553ab6500000000", "ab6aab53006aab52", 0, 247114317, "123916c6485cf23bfea95654a8815fbf04ce4d21a3b7f862805c241472906658"],
+	["7888b71403f6d522e414d4ca2e12786247acf3e78f1918f6d727d081a79813d129ee8befce0100000009ab516a6353ab6365abffffffff4a882791bf6400fda7a8209fb2c83c6eef51831bdf0f5dacde648859090797ec030000000153ffffffffbb08957d59fa15303b681bad19ccf670d7d913697a2f4f51584bf85fcf91f1f30200000008526565ac52ac63acffffffff0227c0e8050000000001ac361dc801000000000800515165ab00ab0000000000", "656a", 2, 1869281295, "f43378a0b7822ad672773944884e866d7a46579ee34f9afc17b20afc1f6cf197"],
+	["cc4dda57047bd0ca6806243a6a4b108f7ced43d8042a1acaa28083c9160911cf47eab910c40200000007526a0000ab6a63e4154e581fcf52567836c9a455e8b41b162a78c85906ccc1c2b2b300b4c69caaaa2ba0230300000008ab5152ac5100ab65ffffffff69696b523ed4bd41ecd4d65b4af73c9cf77edf0e066138712a8e60a04614ea1c0300000004ab6a000016c9045c7df7836e05ac4b2e397e2dd72a5708f4a8bf6d2bc36adc5af3cacefcf074b8b403000000065352ac5252acffffffff01d7e380050000000000cf4e699a", "525163656351", 1, -776533694, "ff18c5bffd086e00917c2234f880034d24e7ea2d1e1933a28973d134ca9e35d2"],
+	["b7877f82019c832707a60cf14fba44cfa254d787501fdd676bd58c744f6e951dbba0b3b77f0200000009ac515263ac53525300a5a36e500148f89c0500000000085265ac6a6a65acab00000000", "6563", 0, -1785108415, "cb6e4322955af12eb29613c70e1a00ddbb559c887ba844df0bcdebed736dffbd"],
+	["aeb14046045a28cc59f244c2347134d3434faaf980961019a084f7547218785a2bd03916f3000000000165f852e6104304955bda5fa0b75826ee176211acc4a78209816bbb4419feff984377b2352200000000003a94a5032df1e0d60390715b4b188c330e4bb7b995f07cdef11ced9d17ee0f60bb7ffc8e0100000002516513e343a5c1dc1c80cd4561e9dddad22391a2dbf9c8d2b6048e519343ca1925a9c6f0800a020000000665516365ac513180144a0290db27000000000006ab655151ab5138b187010000000007ab5363abac516a9e5cd98a", "53ac", 0, 478591320, "e8d89a302ae626898d4775d103867a8d9e81f4fd387af07212adab99946311ef"],
+	["c9270fe004c7911b791a00999d108ce42f9f1b19ec59143f7b7b04a67400888808487bd59103000000066a0052ac6565b905e76687be2dd7723b22c5e8269bc0f2000a332a289cfc40bc0d617cfe3214a61a85a30300000007ac63ac00635251560871209f21eb0268f175b8b4a06edd0b04162a974cf8b5dada43e499a1f22380d35ede0300000000792213fc58b6342cc8100079f9f5f046fb89f2d92cf0a2cb6d07304d32d9da858757037c0000000008abab51636565516affffffff02c72a8b03000000000452acac530dfb9f05000000000096f94307", "5253ab536351", 3, 543688436, "0278adbcc476d135493ae9bdcd7b3c2002df17f2d81c17d631c50c73e546c264"],
+	["57a5a04c0278c8c8e243d2df4bb716f81d41ac41e2df153e7096f5682380c4f441888d9d260300000004ab63ab6afdbe4203525dff42a7b1e628fe22bccaa5edbb34d8ab02faff198e085580ea5fcdb0c61b0000000002ac6affffffff03375e6c05000000000663ab516a6a513cb6260400000000007ca328020000000006516a636a52ab94701cc7", "0053ac5152", 0, -550925626, "b7ca991ab2e20d0158168df2d3dd842a57ab4a3b67cca8f45b07c4b7d1d11126"],
+	["072b75a504ad2550c2e9a02614bc9b2a2f50b5b553af7b87c0ef07c64ddc8d8934c96d216401000000036aabaca1387242a5bcd21099b016ad6045bed7dce603472757d9822cc5f602caa4ae20414d378b02000000026a63e4ac816734acdc969538d6f70b8ab43a2589f55e0177a4dc471bdd0eb61d59f0f46f6bb801000000065351526aab52d9f2977be76a492c3a7617b7a16dc29a3b0a7618f328c2f7d4fd9bafe760dc427a5066ef000000000465635165ffffffff02c5793600000000000165296820050000000002ac6300000000", "53006a6aac0052ab", 2, 66084636, "437e89bb6f70fd2ed2feef33350b6f6483b891305e574da03e580b3efd81ae13"],
+	["7e27c42d0279c1a05eeb9b9faedcc9be0cab6303bde351a19e5cbb26dd0d594b9d74f40d2b020000000200518c8689a08a01e862d5c4dcb294a2331912ff11c13785be7dce3092f154a005624970f84e0200000000500cf5a601e74c1f0000000000076aab52636a6a5200000000", "6500006a5351", 0, 449533391, "535ba819d74770d4d613ee19369001576f98837e18e1777b8246238ff2381dd0"],
+	["11414de403d7f6c0135a9df01cb108c1359b8d4e105be50a3dcba5e6be595c8817217490b20000000003005263ffffffff0c6becb9c3ad301c8dcd92f5cbc07c8bed7973573806d1489316fc77a829da03030000000700005253535352ffffffff2346d74ff9e12e5111aa8779a2025981850d4bf788a48de72baa2e321e4bc9ca00000000056352acab63cc585b64045e0385050000000009ab5253ab516aacac00efa9cf0300000000065200635151acbe80330400000000070063635100ab000be159050000000007525300655300ac00000000", "51656a0051ab", 0, 683137826, "d4737f3b58f3e5081b35f36f91acde89dda00a6a09d447e516b523e7a99264d5"],
+	["1c6b5f29033fc139338658237a42456123727c8430019ca25bd71c6168a9e35a2bf54538d80100000008536aac52ac6a6a52ffffffff3fb36be74036ff0c940a0247c451d923c65f826793d0ac2bb3f01ecbec8033290100000007ab000051ab6363ffffffff5d9eca0cf711685105bd060bf7a67321eaef95367acffab36ce8dedddd632ee2000000000652ac6a63ac517167319e032d26de040000000003516363dc38fb010000000000b37b00000000000006ab520051ac534baba51f", "636300ababac6563", 0, -2049129935, "3282a2ec6b8c87c9303e6060c17b421687db1bd35fbfa0345b48f2490e15b6cc"],
+	["978b9dad0214cfc7ce392d74d9dcc507350dc34007d72e4125861c63071ebf2cc0a6fd4856020000000651ac6a6aab52ffffffff47f20734e3370e733f87a6edab95a7a268ae44db7a8974e255614836b22938720200000008635265ac51516553ffffffff0137b2560100000000035252ac2f3363e9", "006aab6352", 1, 2014249801, "55611a5fb1483bce4c14c33ed15198130e788b72cd8929b2ceef4dd68b1806bf"],
+	["442f1c8703ab39876153c241ab3d69f432ba6db4732bea5002be45c8ca10c3a2356fe0e9590300000001accb2b679cab7c58a660cb6d4b3452c21cd7251a1b77a52c300f655f5baeb6fa27ff5b79880300000003005252e5ccf55712bc8ed6179f6726f8a78f3018a7a0391594b7e286ef5ee99efdcde302a102cc0200000009006352526351536a63ffffffff04443f63030000000006536a63ab63651405fb020000000009ac535351525300ab6a9f172b000000000004ab535263ad5c50050000000008656a65ab630000ac00000000", "65636aab006552", 2, 2125838294, "b3ff10f21e71ebc8b25fe058c4074c42f08617e0dcc03f9e75d20539d3242644"],
+	["2b3470dd028083910117f86614cdcfb459ee56d876572510be4df24c72e8f58c70d5f5948b03000000066aab65635265da2c3aac9d42c9baafd4b655c2f3efc181784d8cba5418e053482132ee798408ba43ccf90300000000ffffffff047dda4703000000000765516a52ac53009384a603000000000651636a63ab6a8cf57a03000000000352ab6a8cf6a405000000000952636a6a6565525100661e09cb", "ac520063ac6a6a52", 1, 1405647183, "9b360c3310d55c845ef537125662b9fe56840c72136891274e9fedfef56f9bb5"],
+	["d74282b501be95d3c19a5d9da3d49c8a88a7049c573f3788f2c42fc6fa594f59715560b9b00000000009655353525265ac52ac9772121f028f8303030000000003510065af5f47040000000007ac516a6551630000000000", "acab53006363ac", 0, -1113209770, "2f482b97178f17286f693796a756f4d7bd2dfcdbecd4142528eec1c7a3e5101a"],
+	["3a5644a9010f199f253f858d65782d3caec0ac64c3262b56893022b9796086275c9d4d097b02000000009d168f7603a67b30050000000007ac51536a0053acd9d88a050000000007655363535263ab3cf1f403000000000352ac6a00000000", "005363536565acac6a", 0, -1383947195, "6390ab0963cf611e0cea35a71dc958b494b084e6fd71d22217fdc5524787ade6"],
+	["67b3cc43049d13007485a8133b90d94648bcf30e83ba174f5486ab42c9107c69c5530c5e1f0000000003005100ffffffff9870ebb65c14263282ea8d41e4f4f40df16b565c2cf86f1d22a9494cad03a67f01000000016a5a121bee5e359da548e808ae1ad6dfccae7c67cbb8898d811638a1f455a671e822f228ef030000000151c1fcc9f9825f27c0dde27ea709da62a80a2ff9f6b1b86a5874c50d6c37d39ae31fb6c8a0030000000163553b8786020ca74a00000000000665635153ab5275c0760000000000020052e659b05d", "636aab6a6a", 0, -342795451, "f77c3322c97b1681c17b1eba461fa27b07e04c1534e8aaf735a49cab72c7c2e2"],
+	["bda1ff6804a3c228b7a12799a4c20917301dd501c67847d35da497533a606701ad31bf9d5e0300000001ac16a6c5d03cf516cd7364e4cbbf5aeccd62f8fd03cb6675883a0636a7daeb650423cb1291010000000500656553ac4a63c30b6a835606909c9efbae1b2597e9db020c5ecfc0642da6dc583fba4e84167539a8020000000865525353515200acffffffff990807720a5803c305b7da08a9f24b92abe343c42ac9e917a84e1f335aad785d00000000026a52ffffffff04981f20030000000001ab8c762200000000000253ab690b9605000000000151ce88b301000000000753526a6a51006500000000", "000052ac52530000", 1, -1809193140, "5299b0fb7fc16f40a5d6b337e71fcd1eb04d2600aefd22c06fe9c71fe0b0ba54"],
+	["2ead28ff0243b3ab285e5d1067f0ec8724224402b21b9cef9be962a8b0d153d401be99bbee0000000004ac635153ffffffff6985987b7c1360c9fa8406dd6e0a61141709f0d5195f946da55ed83be4e3895301000000020053ffffffff016503d20500000000085251ac6a65656a6a00000000", "51abab", 1, 1723793403, "67483ee62516be17a2431a163e96fd88a08ff2ce8634a52e42c1bc04e30f3f8a"],
+	["db4904e6026b6dd8d898f278c6428a176410d1ffbde75a4fa37cda12263108ccd4ca6137440100000007656a0000515263ffffffff1db7d5005c1c40da0ed17b74cf6b2a6ee2c33c9e0bacda76c0da2017dcac2fc70200000004abab6a53ffffffff0454cf2103000000000153463aef000000000009ab6a630065ab52636387e0ed050000000000e8d16f05000000000352ac63e4521b22", "", 1, 1027042424, "48315a95e49277ab6a2d561ee4626820b7bab919eea372b6bf4e9931ab221d04"],
+	["dca31ad10461ead74751e83d9a81dcee08db778d3d79ad9a6d079cfdb93919ac1b0b61871102000000086500525365ab51ac7f7e9aed78e1ef8d213d40a1c50145403d196019985c837ffe83836222fe3e5955e177e70100000006525152525300ffffffff5e98482883cc08a6fe946f674cca479822f0576a43bf4113de9cbf414ca628060100000006ac53516a5253ffffffff07490b0b898198ec16c23b75d606e14fa16aa3107ef9818594f72d5776805ec502000000036a0052ffffffff01932a2803000000000865ab6551ac6a516a2687aa06", "635300ac", 2, -1880362326, "74d6a2fa7866fd8b74b2e34693e2d6fd690410384b7afdcd6461b1ae71d265ce"],
+	["e14e1a9f0442ab44dfc5f6d945ad1ff8a376bc966aad5515421e96ddbe49e529614995cafc03000000055165515165fffffffff97582b8290e5a5cfeb2b0f018882dbe1b43f60b7f45e4dd21dbd3a8b0cfca3b0200000000daa267726fe075db282d694b9fee7d6216d17a8c1f00b2229085495c5dc5b260c8f8cd5d000000000363ac6affffffffaab083d22d0465471c896a438c6ac3abf4d383ae79420617a8e0ba8b9baa872b010000000963526563ac5363ababd948b5ce022113440200000000076a636552006a53229017040000000000e6f62ac8", "526353636a65", 3, -485265025, "1bc8ad76f9b7c366c5d052dc479d6a8a2015566d3a42e93ab12f727692c89d65"],
+	["720d4693025ca3d347360e219e9bc746ef8f7bc88e8795162e5e2f0b0fc99dc17116fc937100000000046353520045cb1fd79824a100d30b6946eab9b219daea2b0cdca6c86367c0c36af98f19ac64f3575002000000008a1c881003ed16f3050000000008536a63630000abac45e0e704000000000151f6551a05000000000963536565515363abab00000000", "6553ab6a6a510000ab", 1, 1249091393, "a575fa4f59a8e90cd07de012c78fe8f981183bb170b9c50fcc292b8c164cbc3b"],
+	["69df842a04c1410bfca10896467ce664cfa31c681a5dac10106b34d4b9d4d6d0dc1eac01c1000000000551536a5165269835ca4ad7268667b16d0a2df154ec81e304290d5ed69e0069b43f8c89e673328005e200000000076a5153006aacabffffffffc9314bd80b176488f3d634360fcba90c3a659e74a52e100ac91d3897072e3509010000000765abac51636363ffffffff0e0768b13f10f0fbd2fa3f68e4b4841809b3b5ba0e53987c3aaffcf09eee12bf0300000008ac535263526a53ac514f4c2402da8fab0400000000001ef15201000000000451526a52d0ec9aca", "525365ac52", 1, 313967049, "a72a760b361af41832d2c667c7488dc9702091918d11e344afc234a4aea3ec44"],
+	["adf2340d03af5c589cb5d28c06635ac07dd0757b884d4777ba85a6a7c410408ad5efa8b19001000000045100ab00ffffffff808dc0231c96e6667c04786865727013922bcb7db20739b686f0c17f5ba70e8f0300000000fd2332a654b580881a5e2bfec8313f5aa878ae94312f37441bf2d226e7fc953dcf0c77ab000000000163aa73dc580412f8c2050000000005636aacac63da02d502000000000153e74b52020000000001536b293d030000000009636552ababacab526500000000", "000052ab52ababab", 0, -568651175, "2c45d021db545df7167ac03c9ee56473f2398d9b2b739cf3ff3e074501d324f8"],
+	["e4fec9f10378a95199c1dd23c6228732c9de0d7997bf1c83918a5cfd36012476c0c3cba24002000000085165536500ac0000ad08ab93fb49d77d12a7ccdbb596bc5110876451b53a79fdce43104ff1c316ad63501de801000000046a6352ab76af9908463444aeecd32516a04dd5803e02680ed7f16307242a794024d93287595250f4000000000089807279041a82e603000000000200521429100200000000055253636a63f20b940400000000004049ed04000000000500ab5265ab43dfaf7d", "6563526aac", 2, -1923470368, "32f3c012eca9a823bebb9b282240aec40ca65df9f38da43b1dcfa0cac0c0df7e"],
+	["4000d3600100b7a3ff5b41ec8d6ccdc8b2775ad034765bad505192f05d1f55d2bc39d0cbe10100000007ab5165ac6a5163ffffffff034949150100000000026a6a92c9f6000000000008ab6553ab6aab635200e697040000000007636a5353525365237ae7d2", "52000063", 0, -880046683, "c76146f68f43037289aaeb2bacf47408cddc0fb326b350eb4f5ef6f0f8564793"],
+	["eabc0aa701fe489c0e4e6222d72b52f083166b49d63ad1410fb98caed027b6a71c02ab830c03000000075253ab63530065ffffffff01a5dc0b05000000000253533e820177", "", 0, 954499283, "1d849b92eedb9bf26bd4ced52ce9cb0595164295b0526842ab1096001fcd31b1"],
+	["d48d55d304aad0139783b44789a771539d052db565379f668def5084daba0dfd348f7dcf6b00000000006826f59e5ffba0dd0ccbac89c1e2d69a346531d7f995dea2ca6d7e6d9225d81aec257c6003000000096a655200ac656552acffffffffa188ffbd5365cae844c8e0dea6213c4d1b2407274ae287b769ab0bf293e049eb0300000005ac6a6aab51ad1c407c5b116ca8f65ed496b476183f85f072c5f8a0193a4273e2015b1cc288bf03e9e2030000000252abffffffff04076f44040000000006655353abab53be6500050000000003ac65ac3c15040500000000095100ab536353516a52ed3aba04000000000900ac53ab53636aabac00000000", "5253526563acac", 2, -1506108646, "bbee17c8582514744bab5df50012c94b0db4aff5984d2e13a8d09421674404e2"],
+	["9746f45b039bfe723258fdb6be77eb85917af808211eb9d43b15475ee0b01253d33fc3bfc502000000065163006a655312b12562dc9c54e11299210266428632a7d0ee31d04dfc7375dcad2da6e9c11947ced0e000000000009074095a5ac4df057554566dd04740c61490e1d3826000ad9d8f777a93373c8dddc4918a00000000025351ffffffff01287564030000000004636a00ab00000000", "52", 2, -1380411075, "84af1623366c4db68d81f452b86346832344734492b9c23fbb89015e516c60b2"],
+	["8731b64903d735ba16da64af537eaf487b57d73977f390baac57c7b567cb2770dfa2ef65870100000001635aedd990c42645482340eacb0bfa4a0a9e888057389c728b5b6a8691cdeb1a6a67b45e140200000008ac53526a52516551ffffffff45c4f567c47b8d999916fd49642cbc5d10d43c304b99e32d044d35091679cb860100000003006a51ffffffff0176d6c200000000000000000000", "ab6a65ab53", 2, -1221546710, "ccfdba36d9445f4451fb7cbf0752cc89c23d4fc6fff0f3930d20e116f9db0b95"],
+	["f5cfc52f016209ab1385e890c2865a74e93076595d1ca77cbe8fbf2022a2f2061a90fb0f3e010000000253acffffffff027de73f0200000000085252ac510052acac49cd6a020000000000e6c2cb56", "516552535300ab63", 0, -1195302704, "5532717402a2da01a1da912d824964024185ca7e8d4ad1748659dc393a14182b"],
+	["df0a32ae01c4672fd1abd0b2623aae0a1a8256028df57e532f9a472d1a9ceb194267b6ee190200000009536a6a51516a525251b545f9e803469a2302000000000465526500810631040000000000441f5b050000000006530051006aaceb183c76", "536a635252ac6a", 0, 1601138113, "9a0435996cc58bdba09643927fe48c1fc908d491a050abbef8daec87f323c58f"],
+	["d102d10c028b9c721abb259fe70bc68962f6cae384dabd77477c59cbeb1fb26266e091ba3e0100000002516affffffffe8d7305a74f43e30c772109849f4cd6fb867c7216e6d92e27605e69a0818899700000000026a65ecf82d58027db4620500000000026552c28ed3010000000001ab00000000", "0051ab515365", 1, -131815460, "1d1757a782cb5860302128bcbe9398243124a2f82d671a113f74f8e582c7a182"],
+	["cef930ed01c36fcb1d62ceef931bef57098f27a77a4299904cc0cbb44504802d535fb11557010000000153ffffffff02c8657403000000000863ac655253520063d593380400000000046aab536a00000000", "656a0051ab6365ab53", 0, -351313308, "e69dba3efb5c02af2ab1087d0a990678784671f4744d01ca097d71aec14dd8e9"],
+	["b1c0b71804dff30812b92eefb533ac77c4b9fdb9ab2f77120a76128d7da43ad70c20bbfb990200000002536392693e6001bc59411aebf15a3dc62a6566ec71a302141b0c730a3ecc8de5d76538b30f55010000000665535252ac514b740c6271fb9fe69fdf82bf98b459a7faa8a3b62f3af34943ad55df4881e0d93d3ce0ac0200000000c4158866eb9fb73da252102d1e64a3ce611b52e873533be43e6883137d0aaa0f63966f060000000001abffffffff04a605b604000000000851006a656a630052f49a0300000000000252515a94e1050000000009abac65ab0052abab00fd8dd002000000000651535163526a2566852d", "ac5363", 0, -1718831517, "b0dc030661783dd9939e4bf1a6dfcba809da2017e1b315a6312e5942d714cf05"],
+	["6a270ee404ebc8d137cfd4bb6b92aa3702213a3139a579c1fc6f56fbc7edd9574ef17b13f30100000009ab00ab656565ababacffffffffaa65b1ab6c6d87260d9e27a472edceb7dd212483e72d90f08857abf1dbfd46d10100000000fffffffff93c4c9c84c4dbbe8a912b99a2830cfe3401aebc919041de063d660e585fc9f002000000096aabacab52ac6a53acfa6dcef3f28355a8d98eee53839455445eeee83eecd2c854e784efa53cee699dbfecaebd0100000003ab6a51ffffffff04f7d71b050000000009ac6a536aac6a6365513c37650500000000065265abab6a53fa742002000000000039ed82030000000009516aac635165ab51ab2fdabd17", "ab535252526563", 1, -1326210506, "1dec0d5eb921bf5b2df39c8576e19c38d0c17254a4a0b78ac4b5422bcc426258"],
+	["3657e4260304ccdc19936e47bdf058d36167ee3d4eb145c52b224eff04c9eb5d1b4e434dfc0000000001ab58aefe57707c66328d3cceef2e6f56ab6b7465e587410c5f73555a513ace2b232793a74400000000036a006522e69d3a785b61ad41a635d59b3a06b2780a92173f85f8ed428491d0aaa436619baa9c4501000000046351abab2609629902eb7793050000000000a1b967040000000003525353a34d6192", "516a", 0, -1761874713, "0a2ff41f6d155d8d0e37cd9438f3b270df9f9214cda8e95c76d5a239ca189df2"],
+	["a0eb6dc402994e493c787b45d1f946d267b09c596c5edde043e620ce3d59e95b2b5b93d43002000000096a5252526aac63ab6555694287a279e29ee491c177a801cd685b8744a2eab83824255a3bcd08fc0e3ea13fb8820000000009abab6365ab52ab0063ffffffff029e424a040000000008acab53ab516a636a23830f0400000000016adf49c1f9", "ac0065ac6500005252", 1, 669294500, "e05e3d383631a7ed1b78210c13c2eb26564e5577db7ddfcea2583c7c014091d4"],
+	["6e67c0d3027701ef71082204c85ed63c700ef1400c65efb62ce3580d187fb348376a23e9710200000001655b91369d3155ba916a0bc6fe4f5d94cad461d899bb8aaac3699a755838bfc229d6828920010000000765536353526a52ffffffff04c0c792000000000005650052535372f79e000000000001527fc0ee010000000005ac5300ab65d1b3e902000000000251aba942b278", "6a5151", 0, 1741407676, "e657e2c8ec4ebc769ddd3198a83267b47d4f2a419fc737e813812acefad92ff7"],
+	["8f53639901f1d643e01fc631f632b7a16e831d846a0184cdcda289b8fa7767f0c292eb221a00000000046a53abacffffffff037a2daa01000000000553ac6a6a51eac349020000000005ac526552638421b3040000000007006a005100ac63048a1492", "ac65", 0, 1033685559, "da86c260d42a692358f46893d6f91563985d86eeb9ea9e21cd38c2d8ffcfcc4d"],
+	["491f99cb01bdfba1aa235e5538dac081fae9ce55f9622de483afe7e65105c2b0db75d360d200000000045251636340b60f0f041421330300000000096351ac000051636553ce2822040000000005516a00ac5180c8e40300000000025100caa8570400000000020000cfdc8da6", "6a5100516aab655365", 0, -953727341, "397c68803b7ce953666830b0221a5e2bcf897aa2ded8e36a6b76c497dcb1a2e1"],
+	["b3cad3a7041c2c17d90a2cd994f6c37307753fa3635e9ef05ab8b1ff121ca11239a0902e700300000009ab635300006aac5163ffffffffcec91722c7468156dce4664f3c783afef147f0e6f80739c83b5f09d5a09a57040200000004516a6552ffffffff969d1c6daf8ef53a70b7cdf1b4102fb3240055a8eaeaed2489617cd84cfd56cf020000000352ab53ffffffff46598b6579494a77b593681c33422a99559b9993d77ca2fa97833508b0c169f80200000009655300655365516351ffffffff04d7ddf800000000000853536a65ac6351ab09f3420300000000056aab65abac33589d04000000000952656a65655151acac944d6f0400000000006a8004ba", "005165", 1, 1035865506, "fe1dc9e8554deecf8f50c417c670b839cc9d650722ebaaf36572418756075d58"],
+	["e1cfd73b0125add9e9d699f5a45dca458355af175a7bd4486ebef28f1928d87864384d02df02000000036a0051ffffffff0357df030100000000036a5365777e2d04000000000763ab6a00005265f434a601000000000351655100000000", "ab53ab", 0, -1936500914, "950f4b4f72ccdf8a6a0f381265d6c8842fdb7e8b3df3e9742905f643b2432b69"],
+	["cf781855040a755f5ba85eef93837236b34a5d3daeb2dbbdcf58bb811828d806ed05754ab8010000000351ac53ffffffffda1e264727cf55c67f06ebcc56dfe7fa12ac2a994fecd0180ce09ee15c480f7d00000000096351516a51acac00ab53dd49ff9f334befd6d6f87f1a832cddfd826a90b78fd8cf19a52cb8287788af94e939d6020000000700525251ac526310d54a7e8900ed633f0f6f0841145aae7ee0cbbb1e2a0cae724ee4558dbabfdc58ba6855010000000552536a53abfd1b101102c51f910500000000096300656a525252656a300bee010000000009ac52005263635151abe19235c9", "53005365", 2, 1422854188, "d5981bd4467817c1330da72ddb8760d6c2556cd809264b2d85e6d274609fc3a3"],
+	["fea256ce01272d125e577c0a09570a71366898280dda279b021000db1325f27edda41a53460100000002ab53c752c21c013c2b3a01000000000000000000", "65", 0, 1145543262, "076b9f844f6ae429de228a2c337c704df1652c292b6c6494882190638dad9efd"]
+]
diff --git a/haskoin-core.cabal b/haskoin-core.cabal
--- a/haskoin-core.cabal
+++ b/haskoin-core.cabal
@@ -1,166 +1,165 @@
-name:                  haskoin-core
-version:               0.4.2
-synopsis:
-    Implementation of the core Bitcoin protocol features.
-description:
-    Haskoin is a package implementing the core functionalities of the Bitcoin
-    protocol specifications. The following features are provided:
-    .
-    * Hashing functions (sha-256, ripemd-160)
-    * Base58 encoding
-    * BIP32 extended key derivation and parsing (m/1'/2/3)
-    * BIP39 mnemonic keys
-    * ECDSA cryptographic primitives (using the C library libsecp256k1)
-    * Script parsing and evaluation
-    * Building and signing of standard transactions (regular, multisig, p2sh)
-    * Parsing and manipulation of all Bitcoin protocol types
-    * Bloom filters and partial merkle tree library (used in SPV wallets)
-    * Comprehensive test suite
-    .
-    A wallet implementation is available in haskoin-wallet which uses both this
-    package and the node implementation in haskoin-node.
+-- This file has been generated from package.yaml by hpack version 0.28.2.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: f099018fce29c2b61c3cfaaf7eca0457f46978327c595aaff25b4ef6228be16f
 
-homepage:              http://github.com/haskoin/haskoin
-bug-reports:           http://github.com/haskoin/haskoin/issues
-tested-with:           GHC==8.0.2
-stability:             stable
-license:               PublicDomain
-license-file:          UNLICENSE
-author:                Philippe Laprade, Jean-Pierre Rupp
-maintainer:            xenog@protonmail.com
-category:              Bitcoin, Finance, Network
-build-type:            Simple
-cabal-version:         >= 1.9.2
-extra-source-files:    tests/data/*.json
+name:           haskoin-core
+version:        0.5.0
+synopsis:       Bitcoin & Bitcoin Cash library for Haskell
+description:    Haskoin Core is a complete Bitcoin and Bitcoin Cash library of functions and data types for Haskell developers.
+category:       Bitcoin, Finance, Network
+homepage:       http://github.com/haskoin/haskoin#readme
+bug-reports:    http://github.com/haskoin/haskoin/issues
+author:         Philippe Laprade,
+                Jean-Pierre Rupp
+maintainer:     xenog@protonmail.com
+license:        PublicDomain
+license-file:   UNLICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+extra-source-files:
+    CHANGELOG.md
+    data/forkid_script_tests.json
+    data/forkid_sighash.json
+    data/script_tests.json
+    data/sig_nonstrict.json
+    data/sig_strict.json
+    data/sighash.json
+    README.md
 
 source-repository head
-    type:     git
-    location: git://github.com/haskoin/haskoin.git
+  type: git
+  location: git://github.com/haskoin/haskoin.git
 
 library
-    exposed-modules: Network.Haskoin.Util
-                     Network.Haskoin.Crypto
-                     Network.Haskoin.Node
-                     Network.Haskoin.Script
-                     Network.Haskoin.Transaction
-                     Network.Haskoin.Block
-                     Network.Haskoin.Constants
-                     Network.Haskoin.Test
-                     Network.Haskoin.Internals
-
-    other-modules: Network.Haskoin.Crypto.Hash
-                   Network.Haskoin.Crypto.Base58
-                   Network.Haskoin.Crypto.Keys
-                   Network.Haskoin.Crypto.ExtendedKeys
-                   Network.Haskoin.Crypto.ECDSA
-                   Network.Haskoin.Crypto.Mnemonic
-                   Network.Haskoin.Node.Types
-                   Network.Haskoin.Node.Message
-                   Network.Haskoin.Node.Bloom
-                   Network.Haskoin.Script.Types
-                   Network.Haskoin.Script.Parser
-                   Network.Haskoin.Script.SigHash
-                   Network.Haskoin.Script.Evaluator
-                   Network.Haskoin.Transaction.Types
-                   Network.Haskoin.Transaction.Builder
-                   Network.Haskoin.Block.Types
-                   Network.Haskoin.Block.Merkle
-                   Network.Haskoin.Test.Util
-                   Network.Haskoin.Test.Crypto
-                   Network.Haskoin.Test.Node
-                   Network.Haskoin.Test.Message
-                   Network.Haskoin.Test.Script
-                   Network.Haskoin.Test.Transaction
-                   Network.Haskoin.Test.Block
-                   Paths_haskoin_core
-
-    extensions: EmptyDataDecls
-                OverloadedStrings
-                FlexibleInstances
-                FlexibleContexts
-                RecordWildCards
-                DeriveDataTypeable
-                GADTs
-
-    build-depends: aeson                    >= 0.7          && < 1.1
-                 , base                     >= 4.8          && < 5
-                 , byteable                 >= 0.1          && < 0.2
-                 , bytestring               >= 0.10         && < 0.11
-                 , base16-bytestring        >= 0.1          && < 0.2
-                 , cereal                   >= 0.5          && < 0.6
-                 , conduit                  >= 1.2          && < 1.3
-                 , containers               >= 0.5          && < 0.6
-                 , cryptohash               >= 0.11         && < 0.12
-                 , deepseq                  >= 1.4          && < 1.5
-                 , either                   >= 4.3          && < 4.5
-                 , mtl                      >= 2.2          && < 2.3
-                 , murmur3                  >= 1.0          && < 1.1
-                 , network                  >= 2.6          && < 2.7
-                 , pbkdf                    >= 1.1          && < 1.2
-                 , QuickCheck               >= 2.6          && < 2.10
-                 , split                    >= 0.2          && < 0.3
-                 , text                     >= 0.11         && < 1.3
-                 , time                     >= 1.4          && < 1.7
-                 , string-conversions       >= 0.4          && < 0.5
-                 , vector                   >= 0.10         && < 0.12
-                 , secp256k1                >= 0.4          && < 0.5
-                 , largeword                >= 1.2.4        && < 1.3
-                 , entropy                  >= 0.3          && < 0.4
-
-    ghc-options:       -Wall
-
-test-suite test-haskoin-core
-    type:              exitcode-stdio-1.0
-    main-is:           Main.hs
-
-    extensions: EmptyDataDecls
-                OverloadedStrings
-
-    other-modules: Network.Haskoin.Util.Tests
-                   Network.Haskoin.Crypto.ECDSA.Tests
-                   Network.Haskoin.Crypto.Base58.Tests
-                   Network.Haskoin.Crypto.Base58.Units
-                   Network.Haskoin.Crypto.Keys.Tests
-                   Network.Haskoin.Crypto.ExtendedKeys.Tests
-                   Network.Haskoin.Crypto.ExtendedKeys.Units
-                   Network.Haskoin.Crypto.Hash.Tests
-                   Network.Haskoin.Crypto.Hash.Units
-                   Network.Haskoin.Crypto.Mnemonic.Tests
-                   Network.Haskoin.Crypto.Mnemonic.Units
-                   Network.Haskoin.Crypto.Units
-                   Network.Haskoin.Node.Units
-                   Network.Haskoin.Script.Tests
-                   Network.Haskoin.Script.Units
-                   Network.Haskoin.Transaction.Tests
-                   Network.Haskoin.Transaction.Units
-                   Network.Haskoin.Block.Tests
-                   Network.Haskoin.Block.Units
-                   Network.Haskoin.Json.Tests
-                   Network.Haskoin.Cereal.Tests
-
-    build-depends: aeson                          >= 0.7        && < 1.1
-                 , base                           >= 4.8        && < 5
-                 , binary                         >= 0.8        && < 0.9
-                 , bytestring                     >= 0.10       && < 0.11
-                 , cereal                         >= 0.5        && < 0.6
-                 , containers                     >= 0.5        && < 0.6
-                 , haskoin-core
-                 , mtl                            >= 2.2        && < 2.3
-                 , split                          >= 0.2        && < 0.3
-                 , HUnit                          >= 1.2        && < 1.6
-                 , QuickCheck                     >= 2.6        && < 2.10
-                 , test-framework                 >= 0.8        && < 0.9
-                 , test-framework-quickcheck2     >= 0.3        && < 0.4
-                 , test-framework-hunit           >= 0.3        && < 0.4
-                 , text                           >= 0.11       && < 1.3
-                 , unordered-containers           >= 0.2        && < 0.3
-                 , string-conversions             >= 0.4        && < 0.5
-                 , largeword                      >= 1.2        && < 1.3
-                 , secp256k1                      >= 0.4        && < 0.5
-                 , safe
-                 , vector
-                 , scientific
-
-    ghc-options: -Wall
-    hs-source-dirs: tests
+  hs-source-dirs:
+      src
+  build-depends:
+      HUnit
+    , QuickCheck
+    , aeson
+    , array
+    , base >=4.7 && <5
+    , base16-bytestring
+    , bytestring
+    , cereal
+    , conduit
+    , containers
+    , cryptonite
+    , deepseq
+    , entropy
+    , hashable
+    , hspec
+    , memory
+    , mtl
+    , murmur3
+    , network
+    , safe
+    , scientific
+    , secp256k1
+    , split
+    , string-conversions
+    , text
+    , time
+    , transformers
+    , unordered-containers
+    , vector
+  exposed-modules:
+      Haskoin
+      Network.Haskoin.Address
+      Network.Haskoin.Address.Base58
+      Network.Haskoin.Address.CashAddr
+      Network.Haskoin.Address.Bech32
+      Network.Haskoin.Block
+      Network.Haskoin.Block.Headers
+      Network.Haskoin.Block.Merkle
+      Network.Haskoin.Constants
+      Network.Haskoin.Crypto
+      Network.Haskoin.Keys
+      Network.Haskoin.Network
+      Network.Haskoin.Script
+      Network.Haskoin.Test
+      Network.Haskoin.Transaction
+      Network.Haskoin.Util
+  other-modules:
+      Network.Haskoin.Block.Common
+      Network.Haskoin.Crypto.Hash
+      Network.Haskoin.Crypto.Signature
+      Network.Haskoin.Keys.Common
+      Network.Haskoin.Keys.Extended
+      Network.Haskoin.Keys.Mnemonic
+      Network.Haskoin.Network.Bloom
+      Network.Haskoin.Network.Common
+      Network.Haskoin.Network.Message
+      Network.Haskoin.Script.Common
+      Network.Haskoin.Script.SigHash
+      Network.Haskoin.Script.Standard
+      Network.Haskoin.Test.Address
+      Network.Haskoin.Test.Block
+      Network.Haskoin.Test.Crypto
+      Network.Haskoin.Test.Keys
+      Network.Haskoin.Test.Message
+      Network.Haskoin.Test.Network
+      Network.Haskoin.Test.Script
+      Network.Haskoin.Test.Transaction
+      Network.Haskoin.Test.Util
+      Network.Haskoin.Transaction.Builder
+      Network.Haskoin.Transaction.Common
+      Paths_haskoin_core
+  default-language: Haskell2010
 
+test-suite spec
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Network.Haskoin.Address.Bech32Spec
+      Network.Haskoin.Address.CashAddrSpec
+      Network.Haskoin.AddressSpec
+      Network.Haskoin.BlockSpec
+      Network.Haskoin.Crypto.HashSpec
+      Network.Haskoin.Crypto.SignatureSpec
+      Network.Haskoin.CryptoSpec
+      Network.Haskoin.Keys.ExtendedSpec
+      Network.Haskoin.Keys.MnemonicSpec
+      Network.Haskoin.KeysSpec
+      Network.Haskoin.NetworkSpec
+      Network.Haskoin.ScriptSpec
+      Network.Haskoin.TransactionSpec
+      Network.Haskoin.UtilSpec
+      Paths_haskoin_core
+  hs-source-dirs:
+      test
+  build-depends:
+      HUnit
+    , QuickCheck
+    , aeson
+    , array
+    , base >=4.7 && <5
+    , base16-bytestring
+    , bytestring
+    , cereal
+    , conduit
+    , containers
+    , cryptonite
+    , deepseq
+    , entropy
+    , hashable
+    , haskoin-core
+    , hspec ==2.*
+    , memory
+    , mtl
+    , murmur3
+    , network
+    , safe
+    , scientific
+    , secp256k1
+    , split
+    , string-conversions
+    , text
+    , time
+    , transformers
+    , unordered-containers
+    , vector
+  default-language: Haskell2010
+  build-tool-depends: hspec-discover:hspec-discover == 2.*
diff --git a/src/Haskoin.hs b/src/Haskoin.hs
new file mode 100644
--- /dev/null
+++ b/src/Haskoin.hs
@@ -0,0 +1,13 @@
+module Haskoin
+    ( module X
+    ) where
+
+import           Network.Haskoin.Address     as X
+import           Network.Haskoin.Block       as X
+import           Network.Haskoin.Constants   as X
+import           Network.Haskoin.Crypto      as X
+import           Network.Haskoin.Keys        as X
+import           Network.Haskoin.Network     as X
+import           Network.Haskoin.Script      as X
+import           Network.Haskoin.Transaction as X
+import           Network.Haskoin.Util        as X
diff --git a/src/Network/Haskoin/Address.hs b/src/Network/Haskoin/Address.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Address.hs
@@ -0,0 +1,181 @@
+{-# LANGUAGE DeriveGeneric     #-}
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Address
+    ( Address(..)
+    , addrToString
+    , stringToAddr
+    , addrFromJSON
+    , pubKeyAddr
+      -- * Private Key Wallet Import Format (WIF)
+    , fromWif
+    , toWif
+    ) where
+
+import           Control.Applicative
+import           Control.DeepSeq
+import           Control.Monad
+import           Data.Aeson                       as A
+import           Data.Aeson.Types
+import qualified Data.ByteString                  as B
+import           Data.Function
+import           Data.List
+import           Data.Maybe
+import           Data.Serialize                   as S
+import           Data.String.Conversions
+import           Data.Text                        (Text)
+import           GHC.Generics                     as G (Generic)
+import           Network.Haskoin.Address.Base58
+import           Network.Haskoin.Address.Bech32
+import           Network.Haskoin.Address.CashAddr
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Keys.Common
+import           Network.Haskoin.Util
+import           Text.Read                        as R
+
+-- | Address format for Bitcoin and Bitcoin Cash.
+data Address
+    -- | pay to public key hash (regular)
+    = PubKeyAddress { getAddrHash160 :: !Hash160
+                    , getAddrNet     :: !Network }
+    -- | pay to script hash
+    | ScriptAddress { getAddrHash160 :: !Hash160
+                    , getAddrNet     :: !Network }
+    -- | pay to witness public key hash
+    | WitnessPubKeyAddress { getAddrHash160 :: !Hash160
+                           , getAddrNet     :: !Network }
+    -- | pay to witness script hash
+    | WitnessScriptAddress { getAddrHash256 :: !Hash256
+                           , getAddrNet     :: !Network }
+    deriving (Eq, G.Generic)
+
+instance Ord Address where
+    compare = compare `on` f
+      where
+        f (PubKeyAddress h _)        = S.encode h
+        f (ScriptAddress h _)        = S.encode h
+        f (WitnessPubKeyAddress h _) = S.encode h
+        f (WitnessScriptAddress h _) = S.encode h
+
+instance NFData Address
+
+-- | Deserializer for binary 'Base58' addresses.
+base58get :: Network -> Get Address
+base58get net = do
+    pfx <- getWord8
+    addr <- S.get
+    f pfx addr
+  where
+    f x a
+        | x == getAddrPrefix net = return (PubKeyAddress a net)
+        | x == getScriptPrefix net = return (ScriptAddress a net)
+        | otherwise = fail "Does not recognize address prefix"
+
+-- | Binary serializer for 'Base58' addresses.
+base58put :: Putter Address
+base58put (PubKeyAddress h net) = do
+        putWord8 (getAddrPrefix net)
+        put h
+base58put (ScriptAddress h net) = do
+        putWord8 (getScriptPrefix net)
+        put h
+base58put _ = error "Cannot serialize this address as Base58"
+
+instance Show Address where
+    showsPrec _ a =
+        case addrToString a of
+            Just s  -> shows s
+            Nothing -> fail "Cannot show this transaction"
+
+instance Read Address where
+    readPrec = do
+        R.String str <- lexP
+        let bs = cs str
+        maybe pfail return $
+            foldl' (\a n -> a <|> stringToAddr n bs) Nothing allNets
+
+instance ToJSON Address where
+    toJSON = A.String . fromMaybe (error "Could not encode address") . addrToString
+
+-- | JSON parsing for Bitcoin addresses. Works with 'Base58', 'CashAddr' and
+-- 'Bech32'.
+addrFromJSON :: Network -> Value -> Parser Address
+addrFromJSON net =
+    withText "address" $ \t ->
+        case stringToAddr net t of
+            Nothing -> fail "could not decode address"
+            Just x  -> return x
+
+-- | Convert address to human-readable string. Uses 'Base58', 'Bech32', or
+-- 'CashAddr' depending on network.
+addrToString :: Address -> Maybe Text
+addrToString a@PubKeyAddress {getAddrHash160 = h, getAddrNet = net}
+    | isNothing (getCashAddrPrefix net) =
+        return $ encodeBase58Check $ runPut $ base58put a
+    | otherwise = cashAddrEncode net 0 (S.encode h)
+addrToString a@ScriptAddress {getAddrHash160 = h, getAddrNet = net}
+    | isNothing (getCashAddrPrefix net) =
+        return $ encodeBase58Check $ runPut $ base58put a
+    | otherwise = cashAddrEncode net 1 (S.encode h)
+addrToString WitnessPubKeyAddress {getAddrHash160 = h, getAddrNet = net} = do
+    hrp <- getBech32Prefix net
+    segwitEncode hrp 0 (B.unpack (S.encode h))
+addrToString WitnessScriptAddress {getAddrHash256 = h, getAddrNet = net} = do
+    hrp <- getBech32Prefix net
+    segwitEncode hrp 0 (B.unpack (S.encode h))
+
+-- | Parse 'Base58', 'Bech32' or 'CashAddr' address, depending on network.
+stringToAddr :: Network -> Text -> Maybe Address
+stringToAddr net bs = cash <|> segwit <|> b58
+  where
+    b58 = eitherToMaybe . runGet (base58get net) =<< decodeBase58Check bs
+    cash = cashAddrDecode net bs >>= \(ver, bs') -> case ver of
+        0 -> do
+            h <- eitherToMaybe (S.decode bs')
+            return $ PubKeyAddress h net
+        1 -> do
+            h <- eitherToMaybe (S.decode bs')
+            return $ ScriptAddress h net
+        _ -> Nothing
+    segwit = do
+        hrp <- getBech32Prefix net
+        (ver, bs') <- segwitDecode hrp bs
+        guard (ver == 0)
+        let bs'' = B.pack bs'
+        case B.length bs'' of
+            20 -> do
+                h <- eitherToMaybe (S.decode bs'')
+                return $ WitnessPubKeyAddress h net
+            32 -> do
+                h <- eitherToMaybe (S.decode bs'')
+                return $ WitnessScriptAddress h net
+            _ -> Nothing
+
+-- | Obtain a P2PKH address from a public key.
+pubKeyAddr :: Network -> PubKeyI -> Address
+pubKeyAddr net k = PubKeyAddress (addressHash (S.encode k)) net
+
+-- | Decode private key from WIF (wallet import format) string.
+fromWif :: Network -> Base58 -> Maybe SecKeyI
+fromWif net wif = do
+    bs <- decodeBase58Check wif
+    -- Check that this is a private key
+    guard (B.head bs == getSecretPrefix net)
+    case B.length bs of
+        -- Uncompressed format
+        33 -> wrapSecKey False <$> secKey (B.tail bs)
+        -- Compressed format
+        34 -> do
+            guard $ B.last bs == 0x01
+            wrapSecKey True <$> secKey (B.tail $ B.init bs)
+        -- Bad length
+        _  -> Nothing
+
+-- | Encode private key into a WIF string.
+toWif :: Network -> SecKeyI -> Base58
+toWif net (SecKeyI k c) =
+    encodeBase58Check . B.cons (getSecretPrefix net) $
+    if c
+        then getSecKey k `B.snoc` 0x01
+        else getSecKey k
diff --git a/src/Network/Haskoin/Address/Base58.hs b/src/Network/Haskoin/Address/Base58.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Address/Base58.hs
@@ -0,0 +1,91 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Address.Base58
+    ( Base58
+    , encodeBase58
+    , decodeBase58
+    , encodeBase58Check
+    , decodeBase58Check
+    ) where
+
+import           Control.Monad
+import           Data.ByteString             (ByteString)
+import qualified Data.ByteString             as BS
+import qualified Data.ByteString.Char8       as C
+import           Data.Maybe                  (fromMaybe, isJust, listToMaybe)
+import           Data.Serialize              as S
+import           Data.String.Conversions     (cs)
+import           Data.Text                   (Text)
+import qualified Data.Text                   as T
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Util
+import           Numeric                     (readInt, showIntAtBase)
+
+-- | 'Base58' classic Bitcoin address format.
+type Base58 = Text
+
+-- | Symbols for Base58 encoding.
+b58Data :: ByteString
+b58Data = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
+
+-- | Convert a number less than or equal to provided integer into a 'Base58'
+-- character.
+b58 :: Int -> Char
+b58 = C.index b58Data
+
+-- | Convert a 'Base58' character into the number it represents.
+b58' :: Char -> Maybe Int
+b58' = flip C.elemIndex b58Data
+
+-- | Encode an arbitrary-length 'Integer' into a 'Base58' string. Leading zeroes
+-- will not be part of the resulting string.
+encodeBase58I :: Integer -> Base58
+encodeBase58I i = cs $ showIntAtBase 58 b58 i ""
+
+-- | Decode a 'Base58' string into an arbitrary-length 'Integer'.
+decodeBase58I :: Base58 -> Maybe Integer
+decodeBase58I s =
+    case go of
+        Just (r,[]) -> Just r
+        _           -> Nothing
+  where
+    p  = isJust . b58'
+    f  = fromMaybe e . b58'
+    go = listToMaybe $ readInt 58 p f (cs s)
+    e  = error "Could not decode base58"
+
+-- | Encode an arbitrary 'ByteString' into a its 'Base58' representation,
+-- preserving leading zeroes.
+encodeBase58 :: ByteString -> Base58
+encodeBase58 bs =
+    l `mappend` r
+  where
+    (z, b) = BS.span (== 0) bs
+    l = cs $ BS.replicate (BS.length z) (BS.index b58Data 0) -- preserve leading 0's
+    r | BS.null b = T.empty
+      | otherwise = encodeBase58I $ bsToInteger b
+
+-- | Decode a 'Base58'-encoded 'Text' to a 'ByteString'.
+decodeBase58 :: Base58 -> Maybe ByteString
+decodeBase58 t =
+    BS.append prefix <$> r
+  where
+    (z, b) = BS.span (== BS.index b58Data 0) (cs t)
+    prefix = BS.replicate (BS.length z) 0 -- preserve leading 1's
+    r | BS.null b = Just BS.empty
+      | otherwise = integerToBS <$> decodeBase58I (cs b)
+
+-- | Computes a checksum for the input 'ByteString' and encodes the input and
+-- the checksum as 'Base58'.
+encodeBase58Check :: ByteString -> Base58
+encodeBase58Check bs =
+    encodeBase58 $ BS.append bs $ encode $ checkSum32 bs
+
+-- | Decode a 'Base58'-encoded string that contains a checksum. This function
+-- returns 'Nothing' if the input string contains invalid 'Base58' characters or
+-- if the checksum fails.
+decodeBase58Check :: Base58 -> Maybe ByteString
+decodeBase58Check bs = do
+    rs <- decodeBase58 bs
+    let (res, chk) = BS.splitAt (BS.length rs - 4) rs
+    guard $ chk == encode (checkSum32 res)
+    return res
diff --git a/src/Network/Haskoin/Address/Bech32.hs b/src/Network/Haskoin/Address/Bech32.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Address/Bech32.hs
@@ -0,0 +1,219 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+{- Copied from reference implementation contributed by Marko Bencun -}
+module Network.Haskoin.Address.Bech32
+    ( HRP
+    , Bech32
+    , Data
+    , bech32Encode
+    , bech32Decode
+    , toBase32
+    , toBase256
+    , segwitEncode
+    , segwitDecode
+    , Word5(..)
+    , word5
+    , fromWord5
+    ) where
+
+import           Control.Monad         (guard)
+import           Data.Array            (Array, assocs, bounds, listArray, (!),
+                                        (//))
+import           Data.Bits             (Bits, testBit, unsafeShiftL,
+                                        unsafeShiftR, xor, (.&.), (.|.))
+import qualified Data.ByteString       as B
+import           Data.Char             (toUpper)
+import           Data.Foldable         (foldl')
+import           Data.Functor.Identity (Identity, runIdentity)
+import           Data.Ix               (Ix (..))
+import           Data.Text             (Text)
+import qualified Data.Text             as T
+import qualified Data.Text.Encoding    as E
+import           Data.Word             (Word8)
+
+-- | Bech32 human-readable string.
+type Bech32 = Text
+
+-- | Human-readable part of 'Bech32' address.
+type HRP = Text
+
+-- | Data part of 'Bech32' address.
+type Data = [Word8]
+
+(.>>.), (.<<.) :: Bits a => a -> Int -> a
+(.>>.) = unsafeShiftR
+(.<<.) = unsafeShiftL
+
+-- | Five-bit word for Bech32.
+newtype Word5 =
+    UnsafeWord5 Word8
+    deriving (Eq, Ord)
+
+instance Ix Word5 where
+    range (UnsafeWord5 m, UnsafeWord5 n) = map UnsafeWord5 $ range (m, n)
+    index (UnsafeWord5 m, UnsafeWord5 n) (UnsafeWord5 i) = index (m, n) i
+    inRange (m, n) i = m <= i && i <= n
+
+-- | Convert an integer number into a five-bit word.
+word5 :: Integral a => a -> Word5
+word5 x = UnsafeWord5 (fromIntegral x .&. 31)
+{-# INLINE word5 #-}
+{-# SPECIALIZE INLINE word5 :: Word8 -> Word5 #-}
+
+-- | Convert a five-bit word into a number.
+fromWord5 :: Num a => Word5 -> a
+fromWord5 (UnsafeWord5 x) = fromIntegral x
+{-# INLINE fromWord5 #-}
+{-# SPECIALIZE INLINE fromWord5 :: Word5 -> Word8 #-}
+
+-- | 'Bech32' character map as array of five-bit integers to character.
+charset :: Array Word5 Char
+charset =
+    listArray (UnsafeWord5 0, UnsafeWord5 31) "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+
+-- | Convert a character to its five-bit value from 'Bech32' 'charset'.
+charsetMap :: Char -> Maybe Word5
+charsetMap c
+    | inRange (bounds inv) upperC = inv ! upperC
+    | otherwise = Nothing
+  where
+    upperC = toUpper c
+    inv = listArray ('0', 'Z') (repeat Nothing) // map swap (assocs charset)
+    swap (a, b) = (toUpper b, Just a)
+
+-- | Calculate or validate 'Bech32' checksum.
+bech32Polymod :: [Word5] -> Word
+bech32Polymod values = foldl' go 1 values .&. 0x3fffffff
+  where
+    go chk value =
+        foldl' xor chk' [g | (g, i) <- zip generator [25 ..], testBit chk i]
+      where
+        generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
+        chk' = chk .<<. 5 `xor` fromWord5 value
+
+-- | Convert human-readable part of 'Bech32' string into a list of five-bit
+-- words.
+bech32HRPExpand :: HRP -> [Word5]
+bech32HRPExpand hrp =
+    map (UnsafeWord5 . (.>>. 5)) hrpBytes ++
+    [UnsafeWord5 0] ++ map word5 hrpBytes
+  where
+    hrpBytes = B.unpack $ E.encodeUtf8 hrp
+
+-- | Calculate checksum for a string of five-bit words.
+bech32CreateChecksum :: HRP -> [Word5] -> [Word5]
+bech32CreateChecksum hrp dat = [word5 (polymod .>>. i) | i <- [25,20 .. 0]]
+  where
+    values = bech32HRPExpand hrp ++ dat
+    polymod =
+        bech32Polymod (values ++ map UnsafeWord5 [0, 0, 0, 0, 0, 0]) `xor` 1
+
+-- | Verify checksum for a human-readable part and string of five-bit words.
+bech32VerifyChecksum :: HRP -> [Word5] -> Bool
+bech32VerifyChecksum hrp dat = bech32Polymod (bech32HRPExpand hrp ++ dat) == 1
+
+-- | Maximum length of a Bech32 result.
+maxBech32Length :: Int
+maxBech32Length = 90
+
+-- | Encode string of five-bit words into 'Bech32' using a provided
+-- human-readable part. Can fail if 'HRP' is invalid or result would be longer
+-- than 90 characters.
+bech32Encode :: HRP -> [Word5] -> Maybe Bech32
+bech32Encode hrp dat = do
+    guard $ checkHRP hrp
+    let dat' = dat ++ bech32CreateChecksum hrp dat
+        rest = map (charset !) dat'
+        result = T.concat [T.toLower hrp, T.pack "1", T.pack rest]
+    guard $ T.length result <= maxBech32Length
+    return result
+
+-- | Check that human-readable part is valid for a 'Bech32' string.
+checkHRP :: HRP -> Bool
+checkHRP hrp = not (T.null hrp) && T.all (\char -> char >= '\x21' && char <= '\x7e') hrp
+
+-- | Decode human-readable 'Bech32' string into a human-readable part and a
+-- string of five-bit words.
+bech32Decode :: Bech32 -> Maybe (HRP, [Word5])
+bech32Decode bech32 = do
+    guard $ T.length bech32 <= maxBech32Length
+    guard $ T.toUpper bech32 == bech32 || lowerBech32 == bech32
+    let (hrp, dat) = T.breakOnEnd "1" lowerBech32
+    guard $ T.length dat >= 6
+    hrp' <- T.stripSuffix "1" hrp
+    guard $ checkHRP hrp'
+    dat' <- mapM charsetMap $ T.unpack dat
+    guard $ bech32VerifyChecksum hrp' dat'
+    return (hrp', take (T.length dat - 6) dat')
+  where
+    lowerBech32 = T.toLower bech32
+
+type Pad f = Int -> Int -> Word -> [[Word]] -> f [[Word]]
+
+yesPadding :: Pad Identity
+yesPadding _ 0 _ result        = return result
+yesPadding _ _ padValue result = return $ [padValue] : result
+{-# INLINE yesPadding #-}
+
+noPadding :: Pad Maybe
+noPadding frombits bits padValue result = do
+    guard $ bits < frombits && padValue == 0
+    return result
+{-# INLINE noPadding #-}
+
+-- | Big endian conversion of a bytestring from base \(2^{frombits}\) to base
+-- \(2^{tobits}\). {frombits} and {twobits} must be positive and
+-- \(2^{frombits}\) and \(2^{tobits}\) must be smaller than the size of Word.
+-- Every value in 'dat' must be strictly smaller than \(2^{frombits}\).
+convertBits :: Functor f => [Word] -> Int -> Int -> Pad f -> f [Word]
+convertBits dat frombits tobits pad = concat . reverse <$> go dat 0 0 []
+  where
+    go [] acc bits result =
+        let padValue = (acc .<<. (tobits - bits)) .&. maxv
+        in pad frombits bits padValue result
+    go (value:dat') acc bits result =
+        go dat' acc' (bits' `rem` tobits) (result' : result)
+      where
+        acc' = (acc .<<. frombits) .|. fromIntegral value
+        bits' = bits + frombits
+        result' =
+            [ (acc' .>>. b) .&. maxv
+            | b <- [bits' - tobits,bits' - 2 * tobits .. 0]
+            ]
+    maxv = (1 .<<. tobits) - 1
+{-# INLINE convertBits #-}
+
+-- | Convert from eight-bit to five-bit word string, adding padding as required.
+toBase32 :: [Word8] -> [Word5]
+toBase32 dat =
+    map word5 $ runIdentity $ convertBits (map fromIntegral dat) 8 5 yesPadding
+
+-- | Convert from five-bit word string to eight-bit word string, ignoring padding.
+toBase256 :: [Word5] -> Maybe [Word8]
+toBase256 dat =
+    map fromIntegral <$> convertBits (map fromWord5 dat) 5 8 noPadding
+
+-- | Check if witness version and program are valid.
+segwitCheck :: Word8 -> Data -> Bool
+segwitCheck witver witprog =
+    witver <= 16 &&
+    if witver == 0
+        then length witprog == 20 || length witprog == 32
+        else length witprog >= 2 && length witprog <= 40
+
+-- | Decode SegWit 'Bech32' address from a string and expected human-readable part.
+segwitDecode :: HRP -> Bech32 -> Maybe (Word8, Data)
+segwitDecode hrp addr = do
+    (hrp', dat) <- bech32Decode addr
+    guard $ (hrp == hrp') && not (null dat)
+    let (UnsafeWord5 witver:datBase32) = dat
+    decoded <- toBase256 datBase32
+    guard $ segwitCheck witver decoded
+    return (witver, decoded)
+
+-- | Encode 'Data' as a SegWit 'Bech32' address. Needs human-readable part and
+-- witness program version.
+segwitEncode :: HRP -> Word8 -> Data -> Maybe Text
+segwitEncode hrp witver witprog = do
+    guard $ segwitCheck witver witprog
+    bech32Encode hrp $ UnsafeWord5 witver : toBase32 witprog
diff --git a/src/Network/Haskoin/Address/CashAddr.hs b/src/Network/Haskoin/Address/CashAddr.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Address/CashAddr.hs
@@ -0,0 +1,188 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Address.CashAddr
+    ( CashPrefix
+    , CashVersion
+    , CashAddr
+    , Cash32
+    , cashAddrDecode
+    , cashAddrEncode
+    , cash32decodeType
+    , cash32encodeType
+    , cash32decode
+    , cash32encode
+    ) where
+
+import           Control.Monad
+import           Data.Bits
+import           Data.ByteString            (ByteString)
+import qualified Data.ByteString            as B
+import qualified Data.ByteString.Char8      as C
+import           Data.Char
+import           Data.List
+import           Data.Text                  (Text)
+import qualified Data.Text                  as T
+import qualified Data.Text.Encoding         as E
+import           Data.Word
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Util
+
+-- | 'CashAddr' prefix, usually shown before the colon in addresses, but sometimes
+-- omitted. It is used in the checksum calculation to avoid parsing an address
+-- from the wrong network.
+type CashPrefix = Text
+
+-- | 'CashAddr' version, until new address schemes appear it will be zero.
+type CashVersion = Word8
+
+-- | High level 'CashAddr' human-reabale string, with explicit or implicit prefix.
+type CashAddr = Text
+
+-- | Low level 'Cash32' is the human-readable low-level encoding used by 'CashAddr'. It
+-- need not encode a valid address but any binary data.
+type Cash32 = Text
+
+-- | Symbols for encoding 'Cash32' data in human-readable strings.
+charset :: String
+charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+
+-- | Get the 32-bit number associated with this 'Cash32' character.
+base32char :: Char -> Maybe Word8
+base32char = fmap fromIntegral . (`elemIndex` charset)
+
+-- | High-Level: decode 'CashAddr' string if it is valid for the
+-- provided 'Network'. Prefix may be omitted from the string.
+cashAddrDecode :: Network -> CashAddr -> Maybe (CashVersion, ByteString)
+cashAddrDecode net ca = do
+    epfx <- getCashAddrPrefix net
+    let (cpfx, cdat) = T.breakOnEnd ":" (T.toLower ca)
+    guard (T.null cpfx || T.init cpfx == epfx)
+    (dpfx, ver, bs) <- cash32decodeType (epfx <> ":" <> cdat)
+    guard (dpfx == epfx)
+    return (ver, bs)
+
+-- | High-Level: encode 'CashAddr' string for the provided network and hash.
+-- Fails if the 'CashVersion' or length of hash 'ByteString' is invalid.
+cashAddrEncode :: Network -> CashVersion -> ByteString -> Maybe CashAddr
+cashAddrEncode net cv bs = do
+    pfx <- getCashAddrPrefix net
+    cash32encodeType pfx cv bs
+
+-- | Mid-Level: decode 'CashAddr' string containing arbitrary prefix, plus a
+-- version byte before the 'ByteString' that encodes type and length.
+cash32decodeType :: Cash32 -> Maybe (CashPrefix, CashVersion, ByteString)
+cash32decodeType ca' = do
+    guard (T.toUpper ca' == ca' || ca == ca')
+    (dpfx, bs) <- cash32decode ca
+    guard (not (B.null bs))
+    let vb = B.head bs
+        pay = B.tail bs
+    (ver, len) <- decodeVersionByte vb
+    guard (B.length pay == len)
+    return (dpfx, ver, pay)
+  where
+    ca = T.toLower ca'
+
+-- | Mid-Level: encode 'CashAddr' string containing arbitrary prefix and
+-- 'CashVersion'. Length must be among those allowed by the standard.
+cash32encodeType :: CashPrefix -> CashVersion -> ByteString -> Maybe Cash32
+cash32encodeType pfx cv bs = do
+    let len = B.length bs
+    vb <- encodeVersionByte cv len
+    let pl = vb `B.cons` bs
+    return (cash32encode pfx pl)
+
+-- | Low-Level: decode 'Cash32' string. 'CashPrefix' must be part of the string.
+-- No version or hash length validation is performed.
+cash32decode :: Cash32 -> Maybe (CashPrefix, ByteString)
+cash32decode text = do
+    let bs = C.map toLower bs'
+    guard (C.map toUpper bs' == bs' || bs == bs')
+    let (pfx', dat) = C.breakEnd (== ':') bs
+    pfx <-
+        if B.null pfx' || pfx' == C.singleton ':'
+            then Nothing
+            else Just (B.init pfx')
+    b32 <- B.pack <$> mapM base32char (C.unpack dat)
+    let px = B.map (.&. 0x1f) pfx
+        pd = px <> B.singleton 0 <> b32
+        cs = cash32Polymod pd
+        bb = B.take (B.length b32 - 8) b32
+    guard (verifyCash32Polymod cs)
+    let out = toBase256 bb
+    return (E.decodeUtf8 pfx, out)
+  where
+    bs' = E.encodeUtf8 text
+
+-- | Low-Level: encode 'Cash32' string for 'CashPrefix' provided. Can encode
+-- arbitrary data. No prefix or length validation is performed.
+cash32encode :: CashPrefix -> ByteString -> Cash32
+cash32encode pfx bs =
+    let b32 = toBase32 bs
+        px = B.map (.&. 0x1f) (E.encodeUtf8 pfx)
+        pd = px <> B.singleton 0 <> b32 <> B.replicate 8 0
+        cs = cash32Polymod pd
+        c32 = B.map f (b32 <> cs)
+        f = fromIntegral . ord . (charset !!) . fromIntegral
+    in pfx <> ":" <> E.decodeUtf8 c32
+
+-- | Convert base of 'ByteString' from eight bits per byte to five bits per
+-- byte, adding padding as necessary.
+toBase32 :: ByteString -> ByteString
+toBase32 =
+    B.pack .
+    map fromIntegral . fst . convertBits True 8 5 . map fromIntegral . B.unpack
+
+-- | Convert base of 'ByteString' from five to eight bits per byte. Ignore
+-- padding to be symmetric with respect to 'toBase32' function.
+toBase256 :: ByteString -> ByteString
+toBase256 =
+    B.pack .
+    map fromIntegral . fst . convertBits False 5 8 . map fromIntegral . B.unpack
+
+-- | Obtain 'CashVersion' and payload length from 'CashAddr' version byte.
+decodeVersionByte :: Word8 -> Maybe (CashVersion, Int)
+decodeVersionByte vb = do
+    guard (vb .&. 0x80 == 0)
+    return (ver, len)
+  where
+    ver = vb `shiftR` 3
+    len = ls !! fromIntegral (vb .&. 0x07)
+    ls = [20, 24, 28, 32, 40, 48, 56, 64]
+
+-- | Encode 'CashVersion' and length into version byte. Fail if version is
+-- larger than five bits, or length incorrect, since that is invalid.
+encodeVersionByte :: CashVersion -> Int -> Maybe Word8
+encodeVersionByte ver len = do
+    guard (ver == ver .&. 0x0f)
+    l <- case len of
+        20 -> Just 0
+        24 -> Just 1
+        28 -> Just 2
+        32 -> Just 3
+        40 -> Just 4
+        48 -> Just 5
+        56 -> Just 6
+        64 -> Just 7
+        _  -> Nothing
+    return ((ver `shiftL` 3) .|. l)
+
+-- | Calculate or validate checksum from base32 'ByteString' (excluding prefix).
+cash32Polymod :: ByteString -> ByteString
+cash32Polymod v =
+    B.pack
+        [fromIntegral (polymod `shiftR` (5 * (7 - i))) .&. 0x1f | i <- [0 .. 7]]
+  where
+    polymod = B.foldl' outer (1 :: Word64) v `xor` 1
+    outer c d =
+        let c0 = (fromIntegral (c `shiftR` 35) :: Word8)
+            c' = ((c .&. 0x07ffffffff) `shiftL` 5) `xor` fromIntegral d
+        in foldl' (inner c0) c' (zip [0 ..] generator)
+    generator =
+        [0x98f2bc8e61, 0x79b76d99e2, 0xf33e5fb3c4, 0xae2eabe2a8, 0x1e4f43e470]
+    inner c0 c (b, g)
+        | c0 `testBit` b = c `xor` g
+        | otherwise = c
+
+-- | Validate that polymod 'ByteString' (eight bytes) is equal to zero.
+verifyCash32Polymod :: ByteString -> Bool
+verifyCash32Polymod = (== B.replicate 8 0)
diff --git a/src/Network/Haskoin/Block.hs b/src/Network/Haskoin/Block.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Block.hs
@@ -0,0 +1,33 @@
+module Network.Haskoin.Block
+    ( module Network.Haskoin.Block.Common
+      -- * Block Header Chain
+    , BlockWork
+    , BlockHeaders(..)
+    , BlockNode(..)
+    , HeaderMemory(..)
+    , BlockMap
+    , getAncestor
+    , isGenesis
+    , initialChain
+    , genesisMap
+    , genesisNode
+    , genesisBlock
+    , connectBlocks
+    , connectBlock
+    , parentBlock
+    , splitPoint
+    , blockLocator
+      -- * Merkle Blocks
+    , MerkleBlock(..)
+    , MerkleRoot
+    , FlagBits
+    , PartialMerkleTree
+    , buildMerkleRoot
+    , buildPartialMerkle
+    , merkleBlockTxs
+    , testMerkleRoot
+    ) where
+
+import           Network.Haskoin.Block.Headers
+import           Network.Haskoin.Block.Merkle
+import           Network.Haskoin.Block.Common
diff --git a/src/Network/Haskoin/Block/Common.hs b/src/Network/Haskoin/Block/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Block/Common.hs
@@ -0,0 +1,316 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module Network.Haskoin.Block.Common
+    ( Block(..)
+    , BlockHeight
+    , Timestamp
+    , BlockHeader(..)
+    , headerHash
+    , BlockLocator
+    , GetBlocks(..)
+    , GetHeaders(..)
+    , BlockHeaderCount
+    , BlockHash(..)
+    , blockHashToHex
+    , hexToBlockHash
+    , Headers(..)
+    , decodeCompact
+    , encodeCompact
+    ) where
+
+import           Control.DeepSeq                    (NFData, rnf)
+import           Control.Monad                      (forM_, liftM2, mzero,
+                                                     replicateM)
+import           Data.Aeson                         (FromJSON, ToJSON,
+                                                     Value (String), parseJSON,
+                                                     toJSON, withText)
+import           Data.Bits                          (shiftL, shiftR, (.&.),
+                                                     (.|.))
+import           Data.ByteString                    (ByteString)
+import qualified Data.ByteString                    as BS
+import           Data.Hashable                      (Hashable)
+import           Data.Maybe                         (fromMaybe)
+import           Data.Serialize                     (Serialize, decode, encode,
+                                                     get, put)
+import           Data.Serialize.Get                 (getWord32le)
+import           Data.Serialize.Put                 (Put, putWord32le)
+import           Data.String                        (IsString, fromString)
+import           Data.String.Conversions            (cs)
+import           Data.Text                          (Text)
+import           Data.Word                          (Word32)
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Network.Common
+import           Network.Haskoin.Transaction.Common
+import           Network.Haskoin.Util
+import qualified Text.Read                          as R
+
+-- | Height of a block in the blockchain, starting at 0 for Genesis.
+type BlockHeight = Word32
+
+-- | Block timestamp as Unix time (seconds since 1970-01-01 00:00 UTC).
+type Timestamp = Word32
+
+-- | Block header and transactions.
+data Block =
+    Block { blockHeader :: !BlockHeader
+          , blockTxns   :: ![Tx]
+          } deriving (Eq, Show, Read)
+
+instance NFData Block where
+    rnf (Block h ts) = rnf h `seq` rnf ts
+
+instance Serialize Block where
+    get = do
+        header     <- get
+        (VarInt c) <- get
+        txs        <- replicateM (fromIntegral c) get
+        return $ Block header txs
+    put (Block h txs) = do
+        put h
+        put $ VarInt $ fromIntegral $ length txs
+        forM_ txs put
+
+-- | Block header hash. To be serialized reversed for display purposes.
+newtype BlockHash = BlockHash
+    { getBlockHash :: Hash256 }
+    deriving (Eq, Ord, NFData, Hashable, Serialize)
+
+instance Show BlockHash where
+    showsPrec _ = shows . blockHashToHex
+
+instance Read BlockHash where
+    readPrec = do
+        R.String str <- R.lexP
+        maybe R.pfail return $ hexToBlockHash $ cs str
+
+instance IsString BlockHash where
+    fromString s =
+        let e = error "Could not read block hash from hex string"
+        in fromMaybe e $ hexToBlockHash $ cs s
+
+instance FromJSON BlockHash where
+    parseJSON = withText "block hash" $
+        maybe mzero return . hexToBlockHash
+
+instance ToJSON BlockHash where
+    toJSON = String . blockHashToHex
+
+-- | Block hashes are reversed with respect to the in-memory byte order in a
+-- block hash when displayed.
+blockHashToHex :: BlockHash -> Text
+blockHashToHex (BlockHash h) = encodeHex (BS.reverse (encode h))
+
+-- | Convert a human-readable hex block hash into a 'BlockHash'. Bytes are
+-- reversed as normal.
+hexToBlockHash :: Text -> Maybe BlockHash
+hexToBlockHash hex = do
+    bs <- BS.reverse <$> decodeHex hex
+    h <- eitherToMaybe (decode bs)
+    return $ BlockHash h
+
+-- | Data type recording information of a 'Block'. The hash of a block is
+-- defined as the hash of this data structure, serialized. The block mining
+-- process involves finding a partial hash collision by varying the nonce in the
+-- 'BlockHeader' and/or additional entropy in the coinbase 'Transaction' of this
+-- 'Block'. Variations in the coinbase will result in different merkle roots in
+-- the 'BlockHeader'.
+data BlockHeader =
+    BlockHeader { blockVersion   :: !Word32      -- 16 bytes
+                  -- | hash of the previous block (parent)
+                , prevBlock      :: !BlockHash   -- 64 bytes
+                  -- | root of the merkle tree of transactions
+                , merkleRoot     :: !Hash256     -- 64 bytes
+                  -- | unix timestamp
+                , blockTimestamp :: !Timestamp   -- 16 bytes
+                  -- | difficulty target
+                , blockBits      :: !Word32      -- 16 bytes
+                  -- | random nonce
+                , bhNonce        :: !Word32      -- 16 bytes
+                } deriving (Eq, Ord, Show, Read) -- 208 bytes (above + 16 bytes)
+
+-- | Compute hash of 'BlockHeader'.
+headerHash :: BlockHeader -> BlockHash
+headerHash = BlockHash . doubleSHA256 . encode
+
+instance NFData BlockHeader where
+    rnf (BlockHeader v p m t b n) =
+        rnf v `seq` rnf p `seq` rnf m `seq`
+        rnf t `seq` rnf b `seq` rnf n
+
+instance Serialize BlockHeader where
+    get = do
+        v <- getWord32le
+        p <- get
+        m <- get
+        t <- getWord32le
+        b <- getWord32le
+        n <- getWord32le
+        return BlockHeader
+            { blockVersion   = v
+            , prevBlock      = p
+            , merkleRoot     = m
+            , blockTimestamp = t
+            , blockBits      = b
+            , bhNonce        = n
+            }
+
+    put (BlockHeader v p m bt bb n) = do
+        putWord32le v
+        put         p
+        put         m
+        putWord32le bt
+        putWord32le bb
+        putWord32le n
+
+-- | A block locator is a set of block headers, denser towards the best block
+-- and sparser towards the genesis block. It starts at the highest block known.
+-- It is used by a node to synchronize against the network. When the locator is
+-- provided to a peer, it will send back block hashes starting from the first
+-- block in the locator that it recognizes.
+type BlockLocator = [BlockHash]
+
+-- | Data type representing a getblocks message request. It is used in the
+-- bitcoin protocol to retrieve blocks from a peer by providing it a
+-- 'BlockLocator' object. The response to a 'GetBlocks' message is an 'Inv'
+-- message containing a list of block hashes that the peer believes this node is
+-- missing. The number of block hashes in that inv message will end at the stop
+-- block hash, at at the tip of the chain, or after 500 entries, whichever comes
+-- earlier.
+data GetBlocks =
+    GetBlocks { -- | protocol version.
+                getBlocksVersion  :: !Word32
+                -- | block locator object
+              , getBlocksLocator  :: !BlockLocator
+                -- | hash of the last desired block
+              , getBlocksHashStop :: !BlockHash
+              } deriving (Eq, Show)
+
+instance NFData GetBlocks where
+    rnf (GetBlocks v l h) = rnf v `seq` rnf l `seq` rnf h
+
+instance Serialize GetBlocks where
+
+    get = GetBlocks <$> getWord32le
+                    <*> (repList =<< get)
+                    <*> get
+      where
+        repList (VarInt c) = replicateM (fromIntegral c) get
+
+    put (GetBlocks v xs h) = putGetBlockMsg v xs h
+
+putGetBlockMsg :: Word32 -> BlockLocator -> BlockHash -> Put
+putGetBlockMsg v xs h = do
+    putWord32le v
+    put $ VarInt $ fromIntegral $ length xs
+    forM_ xs put
+    put h
+
+-- | Similar to the 'GetBlocks' message type but for retrieving block headers
+-- only. The response to a 'GetHeaders' request is a 'Headers' message
+-- containing a list of block headers. A maximum of 2000 block headers can be
+-- returned. 'GetHeaders' is used by simplified payment verification (SPV)
+-- clients to exclude block contents when synchronizing the blockchain.
+data GetHeaders =
+    GetHeaders {
+                 -- | protocol version
+                 getHeadersVersion  :: !Word32
+                 -- | block locator object
+               , getHeadersBL       :: !BlockLocator
+                 -- | hash of the last desired block header
+               , getHeadersHashStop :: !BlockHash
+               } deriving (Eq, Show)
+
+instance NFData GetHeaders where
+    rnf (GetHeaders v l h) = rnf v `seq` rnf l `seq` rnf h
+
+instance Serialize GetHeaders where
+
+    get = GetHeaders <$> getWord32le
+                     <*> (repList =<< get)
+                     <*> get
+      where
+        repList (VarInt c) = replicateM (fromIntegral c) get
+
+    put (GetHeaders v xs h) = putGetBlockMsg v xs h
+
+-- | 'BlockHeader' type with a transaction count as 'VarInt'
+type BlockHeaderCount = (BlockHeader, VarInt)
+
+-- | The 'Headers' type is used to return a list of block headers in
+-- response to a 'GetHeaders' message.
+newtype Headers =
+    Headers { -- | list of block headers with transaction count
+              headersList :: [BlockHeaderCount]
+            }
+    deriving (Eq, Show)
+
+instance NFData Headers where
+    rnf (Headers l) = rnf l
+
+instance Serialize Headers where
+
+    get = Headers <$> (repList =<< get)
+      where
+        repList (VarInt c) = replicateM (fromIntegral c) action
+        action = liftM2 (,) get get
+
+    put (Headers xs) = do
+        put $ VarInt $ fromIntegral $ length xs
+        forM_ xs $ \(a,b) -> put a >> put b
+
+-- | Decode the compact number used in the difficulty target of a block.
+--
+-- The compact format is a representation of a whole number \(N\) using an
+-- unsigned 32-bit number similar to a floating point format. The most
+-- significant 8 bits are the unsigned exponent of base 256. This exponent can
+-- be thought of as the number of bytes of \(N\). The lower 23 bits are the
+-- mantissa. Bit number 24 represents the sign of \(N\).
+--
+-- \[
+-- N = -1^{sign} \times mantissa \times 256^{exponent-3}
+-- \]
+decodeCompact :: Word32 -> (Integer, Bool) -- ^ true means overflow
+decodeCompact nCompact = (if neg then res * (-1) else res, over)
+  where
+    nSize :: Int
+    nSize = fromIntegral nCompact `shiftR` 24
+    nWord' :: Word32
+    nWord' = nCompact .&. 0x007fffff
+    nWord :: Word32
+    nWord | nSize <= 3 = nWord' `shiftR` (8 * (3 - nSize))
+          | otherwise = nWord'
+    res :: Integer
+    res | nSize <= 3 = fromIntegral nWord
+        | otherwise = fromIntegral nWord `shiftL` (8 * (nSize - 3))
+    neg = nWord /= 0 && (nCompact .&. 0x00800000) /= 0
+    over = nWord /= 0 && (nSize > 34 ||
+                          nWord > 0xff && nSize > 33 ||
+                          nWord > 0xffff && nSize > 32)
+
+-- | Encode an 'Integer' to the compact number format used in the difficulty
+-- target of a block.
+encodeCompact :: Integer
+              -> Word32
+encodeCompact i = nCompact
+  where
+    i' = abs i
+    neg = i < 0
+    nSize' :: Int
+    nSize' = let f 0 = 0
+                 f n = 1 + f (n `shiftR` 8)
+             in f i'
+    nCompact''' :: Word32
+    nCompact'''
+        | nSize' <= 3 = fromIntegral $ (low64 .&. i') `shiftL` (8 * (3 - nSize'))
+        | otherwise = fromIntegral $ low64 .&. (i' `shiftR` (8 * (nSize' - 3)))
+    nCompact'' :: Word32
+    nSize :: Int
+    (nCompact'', nSize)
+        | nCompact''' .&. 0x00800000 /= 0 = (nCompact''' `shiftR` 8, nSize' + 1)
+        | otherwise = (nCompact''', nSize')
+    nCompact' :: Word32
+    nCompact' = nCompact'' .|. (fromIntegral nSize `shiftL` 24)
+    nCompact :: Word32
+    nCompact | neg && (nCompact' .&. 0x007fffff /= 0) = nCompact' .|. 0x00800000
+             | otherwise = nCompact'
+    low64 :: Integer
+    low64 = 0xffffffffffffffff
diff --git a/src/Network/Haskoin/Block/Headers.hs b/src/Network/Haskoin/Block/Headers.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Block/Headers.hs
@@ -0,0 +1,722 @@
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE RecordWildCards   #-}
+module Network.Haskoin.Block.Headers
+    ( BlockNode(..)
+    , BlockHeaders(..)
+    , BlockWork
+    , genesisNode
+    , genesisBlock
+    , isGenesis
+    , chooseBest
+      -- * Header Chain Storage Functions
+    , parentBlock
+    , getParents
+    , getAncestor
+    , splitPoint
+    , connectBlocks
+    , connectBlock
+    , blockLocator
+      -- * In-Memory Header Chain Store
+    , HeaderMemory(..)
+    , ShortBlockHash
+    , BlockMap
+    , shortBlockHash
+    , initialChain
+    , genesisMap
+      -- * Helper Functions
+    , appendBlocks
+    , validBlock
+    , validCP
+    , afterLastCP
+    , bip34
+    , validVersion
+    , lastNoMinDiff
+    , nextWorkRequired
+    , nextEdaWorkRequired
+    , nextDaaWorkRequired
+    , computeTarget
+    , getSuitableBlock
+    , nextPowWorkRequired
+    , calcNextWork
+    , isValidPOW
+    , blockPOW
+    , headerWork
+    , diffInterval
+    , blockLocatorNodes
+    , mineBlock
+    , ) where
+
+import           Control.Applicative                ((<|>))
+import           Control.DeepSeq                    (NFData, rnf)
+import           Control.Monad                      (guard, unless, when)
+import           Control.Monad.Except               (ExceptT (..), runExceptT,
+                                                     throwError)
+import           Control.Monad.State.Strict         as State (StateT, get, gets,
+                                                              lift, modify)
+import           Control.Monad.Trans.Maybe
+import           Data.Bits                          (shiftL, shiftR, (.&.))
+import qualified Data.ByteString                    as B
+import           Data.ByteString.Short              (ShortByteString, fromShort,
+                                                     toShort)
+import           Data.Function                      (on)
+import           Data.HashMap.Strict                (HashMap)
+import qualified Data.HashMap.Strict                as HashMap
+import           Data.List                          (sort, sortBy)
+import           Data.Maybe                         (fromMaybe, listToMaybe)
+import           Data.Serialize                     as S (Serialize (..),
+                                                          decode, encode, get,
+                                                          put)
+import           Data.Serialize.Get                 as S
+import           Data.Serialize.Put                 as S
+import           Data.Typeable                      (Typeable)
+import           Data.Word                          (Word32, Word64)
+import           Network.Haskoin.Block.Common
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Transaction.Common
+import           Network.Haskoin.Util
+
+-- | Short version of the block hash. Uses the good end of the hash (the part
+-- that doesn't have a long string of zeroes).
+type ShortBlockHash = Word64
+
+-- | Memory-based map to a serialized 'BlockNode' data structure.
+-- 'ShortByteString' is used to avoid memory fragmentation and make the data
+-- structure compact.
+type BlockMap = HashMap ShortBlockHash ShortByteString
+
+-- | Represents accumulated work in the blockchain so far.
+type BlockWork = Integer
+
+-- | Data structure representing a block header and its position in the
+-- blockchain.
+data BlockNode
+    -- | non-Genesis block header
+    = BlockNode { nodeHeader :: !BlockHeader
+                , nodeHeight :: !BlockHeight
+        -- | accumulated work so far
+                , nodeWork   :: !BlockWork
+        -- | akip magic block hash
+                , nodeSkip   :: !BlockHash }
+    -- | Genesis block header
+    | GenesisNode { nodeHeader :: !BlockHeader
+                  , nodeHeight :: !BlockHeight
+                  , nodeWork   :: !BlockWork }
+    deriving (Show)
+
+instance Serialize BlockNode where
+    get = do
+        nodeHeader <- S.get
+        nodeHeight <- getWord32le
+        nodeWork <- S.get
+        if nodeHeight == 0
+            then return GenesisNode {..}
+            else do
+                nodeSkip <- S.get
+                return BlockNode {..}
+    put bn = do
+        put $ nodeHeader bn
+        putWord32le $ nodeHeight bn
+        put $ nodeWork bn
+        case bn of
+            GenesisNode {} -> return ()
+            BlockNode {}   -> put $ nodeSkip bn
+
+instance NFData BlockNode where
+    rnf BlockNode {..} =
+        rnf nodeHeader `seq` rnf nodeHeight `seq` rnf nodeSkip
+    rnf GenesisNode {..} =
+        rnf nodeHeader `seq` rnf nodeHeight `seq` rnf nodeWork
+
+instance Eq BlockNode where
+    (==) = (==) `on` nodeHeader
+
+instance Ord BlockNode where
+    compare = compare `on` nodeHeight
+
+-- | Memory-based header tree.
+data HeaderMemory = HeaderMemory
+    { memoryHeaderMap  :: !BlockMap
+    , memoryBestHeader :: !BlockNode
+    } deriving (Eq, Typeable)
+
+instance NFData HeaderMemory where
+    rnf HeaderMemory{..} =
+        rnf memoryHeaderMap `seq` rnf memoryBestHeader
+
+-- | Typeclass for block header chain storage monad.
+class Monad m => BlockHeaders m where
+    -- | Add a new 'BlockNode' to the chain. Does not validate.
+    addBlockHeader :: BlockNode -> m ()
+    -- | Get a 'BlockNode' associated with a 'BlockHash'.
+    getBlockHeader :: BlockHash -> m (Maybe BlockNode)
+    -- | Locate the 'BlockNode' for the highest block in the chain
+    getBestBlockHeader :: m BlockNode
+    -- | Set the highest block in the chain.
+    setBestBlockHeader :: BlockNode -> m ()
+    -- | Add a continuous bunch of block headers the chain. Does not validate.
+    addBlockHeaders :: [BlockNode] -> m ()
+    addBlockHeaders = mapM_ addBlockHeader
+
+instance Monad m => BlockHeaders (StateT HeaderMemory m) where
+    addBlockHeader = modify . addBlockHeaderMemory
+    getBlockHeader bh = getBlockHeaderMemory bh <$> State.get
+    getBestBlockHeader = gets memoryBestHeader
+    setBestBlockHeader bn = modify $ \s -> s { memoryBestHeader = bn }
+
+-- | Initialize memory-based chain.
+initialChain :: Network -> HeaderMemory
+initialChain net = HeaderMemory
+    { memoryHeaderMap = genesisMap net
+    , memoryBestHeader = genesisNode net
+    }
+
+-- | Initialize map for memory-based chain.
+genesisMap :: Network -> BlockMap
+genesisMap net =
+    HashMap.singleton
+        (shortBlockHash (headerHash (getGenesisHeader net)))
+        (toShort (encode (genesisNode net)))
+
+-- | Add block header to memory block map.
+addBlockHeaderMemory :: BlockNode -> HeaderMemory -> HeaderMemory
+addBlockHeaderMemory bn s@HeaderMemory{..} =
+    let bm' = addBlockToMap bn memoryHeaderMap
+    in s { memoryHeaderMap = bm' }
+
+-- | Get block header from memory block map.
+getBlockHeaderMemory :: BlockHash -> HeaderMemory -> Maybe BlockNode
+getBlockHeaderMemory bh HeaderMemory {..} = do
+    bs <- shortBlockHash bh `HashMap.lookup` memoryHeaderMap
+    eitherToMaybe . decode $ fromShort bs
+
+-- | Calculate short block hash taking eight non-zero bytes from the 16-byte
+-- hash. This function will take the bytes that are not on the zero-side of the
+-- hash, making colissions between short block hashes difficult.
+shortBlockHash :: BlockHash -> ShortBlockHash
+shortBlockHash = either error id . decode . B.take 8 . encode
+
+-- | Add a block to memory-based block map.
+addBlockToMap :: BlockNode -> BlockMap -> BlockMap
+addBlockToMap node =
+    HashMap.insert
+    (shortBlockHash $ headerHash $ nodeHeader node)
+    (toShort $ encode node)
+
+-- | Get the ancestor of the provided 'BlockNode' at the specified
+-- 'BlockHeight'.
+getAncestor :: BlockHeaders m
+            => BlockHeight
+            -> BlockNode
+            -> m (Maybe BlockNode)
+getAncestor height node
+    | height > nodeHeight node = return Nothing
+    | otherwise = go node
+  where
+    e1 = error "Could not get skip header"
+    e2 = error "Could not get previous block header"
+    go walk
+        | nodeHeight walk > height =
+            let heightSkip = skipHeight (nodeHeight walk)
+                heightSkipPrev = skipHeight (nodeHeight walk - 1)
+             in if not (isGenesis walk) &&
+                   (heightSkip == height ||
+                    (heightSkip > height &&
+                     not
+                         (heightSkipPrev < heightSkip - 2 &&
+                          heightSkipPrev >= height)))
+                    then do
+                        walk' <- fromMaybe e1 <$> getBlockHeader (nodeSkip walk)
+                        go walk'
+                    else do
+                        walk' <-
+                            fromMaybe e2 <$>
+                            getBlockHeader (prevBlock (nodeHeader walk))
+                        go walk'
+        | otherwise = return $ Just walk
+
+-- | Is the provided 'BlockNode' the Genesis block?
+isGenesis :: BlockNode -> Bool
+isGenesis GenesisNode{} = True
+isGenesis BlockNode{}   = False
+
+-- | Build the genesis 'BlockNode' for the supplied 'Network'.
+genesisNode :: Network -> BlockNode
+genesisNode net =
+    GenesisNode
+        { nodeHeader = getGenesisHeader net
+        , nodeHeight = 0
+        , nodeWork = headerWork (getGenesisHeader net)
+        }
+
+-- | Validate a list of continuous block headers and import them to the
+-- blockchain. Return 'Left' on failure with error information.
+connectBlocks :: BlockHeaders m
+              => Network
+              -> Timestamp       -- ^ current time
+              -> [BlockHeader]
+              -> m (Either String [BlockNode])
+connectBlocks _ _ [] = return $ Right []
+connectBlocks net t bhs@(bh:_) =
+    runExceptT $ do
+        unless (chained bhs) $
+            throwError "Blocks to connect do not form a chain"
+        par <-
+            maybeToExceptT
+                "Could not get parent block"
+                (MaybeT (parentBlock bh))
+        pars <- lift $ getParents 10 par
+        bb <- lift getBestBlockHeader
+        bns@(bn:_) <- go par [] bb par pars bhs
+        lift $ addBlockHeaders bns
+        let bb' = chooseBest bn bb
+        when (bb' /= bb) $ lift $ setBestBlockHeader bb'
+        return bns
+  where
+    chained (h1:h2:hs) = headerHash h1 == prevBlock h2 && chained (h2 : hs)
+    chained _          = True
+    skipit lbh ls par
+        | sh == nodeHeight lbh = return lbh
+        | sh < nodeHeight lbh = do
+            skM <- lift $ getAncestor sh lbh
+            case skM of
+                Just sk -> return sk
+                Nothing ->
+                    throwError $
+                    "BUG: Could not get skip for block " ++
+                    show (headerHash $ nodeHeader par)
+        | otherwise = do
+            let sn = ls !! fromIntegral (nodeHeight par - sh)
+            when (nodeHeight sn /= sh) $
+                throwError "BUG: Node height not right in skip"
+            return sn
+      where
+        sh = skipHeight (nodeHeight par + 1)
+    go _ acc _ _ _ [] = return acc
+    go lbh acc bb par pars (h:hs) = do
+        sk <- skipit lbh acc par
+        bn <- ExceptT . return $ validBlock net t bb par pars h sk
+        go lbh (bn : acc) (chooseBest bn bb) bn (take 10 $ par : pars) hs
+
+-- | Block's parent. If the block header is in the store, its parent must also
+-- be there. No block header get deleted or pruned from the store.
+parentBlock :: BlockHeaders m
+            => BlockHeader
+            -> m (Maybe BlockNode)
+parentBlock bh = getBlockHeader (prevBlock bh)
+
+-- | Validate and connect single block header to the blockchain. Return 'Left' if fails
+-- to be validated.
+connectBlock ::
+       BlockHeaders m
+    => Network
+    -> Timestamp -- ^ current time
+    -> BlockHeader
+    -> m (Either String BlockNode)
+connectBlock net t bh =
+    runExceptT $ do
+        par <-
+            maybeToExceptT
+                "Could not get parent block"
+                (MaybeT (parentBlock bh))
+        pars <- lift $ getParents 10 par
+        skM <- lift $ getAncestor (skipHeight (nodeHeight par + 1)) par
+        sk <-
+            case skM of
+                Just sk -> return sk
+                Nothing ->
+                    throwError $
+                    "BUG: Could not get skip for block " ++
+                    show (headerHash $ nodeHeader par)
+        bb <- lift getBestBlockHeader
+        bn <- ExceptT . return $ validBlock net t bb par pars bh sk
+        let bb' = chooseBest bb bn
+        lift $ addBlockHeader bn
+        when (bb /= bb') . lift $ setBestBlockHeader bb'
+        return bn
+
+-- | Validate this block header. Build a 'BlockNode' if successful.
+validBlock :: Network
+           -> Timestamp     -- ^ current time
+           -> BlockNode     -- ^ best block
+           -> BlockNode     -- ^ immediate parent
+           -> [BlockNode]   -- ^ 10 parents above
+           -> BlockHeader   -- ^ header to validate
+           -> BlockNode     -- ^ skip node (black magic)
+           -> Either String BlockNode
+validBlock net t bb par pars bh sk = do
+    let mt = medianTime . map (blockTimestamp . nodeHeader) $ par : pars
+        nt = blockTimestamp bh
+        hh = headerHash bh
+        nv = blockVersion bh
+        ng = nodeHeight par + 1
+        aw = nodeWork par + headerWork bh
+    unless (isValidPOW net bh) $
+        Left $ "Proof of work failed: " ++ show (headerHash bh)
+    unless (nt <= t + 2 * 60 * 60) $
+        Left $ "Invalid header timestamp: " ++ show nt
+    unless (nt >= mt) $
+        Left $ "Block timestamp too early: " ++ show nt
+    unless (afterLastCP net (nodeHeight bb) ng) $
+        Left $ "Rewriting pre-checkpoint chain: " ++ show ng
+    unless (validCP net ng hh) $
+        Left $ "Rejected checkpoint: " ++ show ng
+    unless (bip34 net ng hh) $
+        Left $ "Rejected BIP-34 block: " ++ show hh
+    unless (validVersion net ng nv) $
+        Left $ "Invalid block version: " ++ show nv
+    return BlockNode { nodeHeader = bh
+                     , nodeHeight = ng
+                     , nodeWork = aw
+                     , nodeSkip = headerHash $ nodeHeader sk
+                     }
+
+-- | Return the median of all provided timestamps. Can be unsorted. Error on
+-- empty list.
+medianTime :: [Timestamp] -> Timestamp
+medianTime ts
+    | null ts = error "Cannot compute median time of empty header list"
+    | otherwise = sort ts !! (length ts `div` 2)
+
+-- | Calculate the height of the skip (magic) block that corresponds to the
+-- given height. The block hash of the ancestor at that height will be placed on
+-- the 'BlockNode' structure to help locate ancestors at any height quickly.
+skipHeight :: BlockHeight -> BlockHeight
+skipHeight height
+    | height < 2 = 0
+    | height .&. 1 /= 0 = invertLowestOne (invertLowestOne $ height - 1) + 1
+    | otherwise = invertLowestOne height
+
+-- | Part of the skip black magic calculation.
+invertLowestOne :: BlockHeight -> BlockHeight
+invertLowestOne height = height .&. (height - 1)
+
+-- | Get a number of parents for the provided block.
+getParents :: BlockHeaders m
+           => Int
+           -> BlockNode
+           -> m [BlockNode]   -- ^ starts from immediate parent
+getParents = getpars []
+  where
+    getpars acc 0 _ = return $ reverse acc
+    getpars acc _ GenesisNode{} = return $ reverse acc
+    getpars acc n BlockNode{..} = do
+        parM <- getBlockHeader $ prevBlock nodeHeader
+        case parM of
+            Just bn -> getpars (bn : acc) (n - 1) bn
+            Nothing -> error "BUG: All non-genesis blocks should have a parent"
+
+-- | Verify that checkpoint location is valid.
+validCP :: Network
+        -> BlockHeight  -- ^ new child height
+        -> BlockHash    -- ^ new child hash
+        -> Bool
+validCP net height newChildHash =
+    case lookup height (getCheckpoints net) of
+        Just cpHash -> cpHash == newChildHash
+        Nothing     -> True
+
+-- | New block height above the last checkpoint imported. Used to prevent a
+-- reorg below the highest checkpoint that was already imported.
+afterLastCP :: Network
+            -> BlockHeight  -- ^ best height
+            -> BlockHeight  -- ^ new imported block height
+            -> Bool
+afterLastCP net bestHeight newChildHeight =
+    case lM of
+        Just l  -> l < newChildHeight
+        Nothing -> True
+  where
+    lM =
+        listToMaybe . reverse $
+        [c | (c, _) <- getCheckpoints net, c <= bestHeight]
+
+-- | This block should be at least version 2 (BIP34). Block height must be
+-- included in the coinbase transaction to prevent non-unique transaction
+-- hashes.
+bip34 :: Network
+      -> BlockHeight  -- ^ new child height
+      -> BlockHash    -- ^ new child hash
+      -> Bool
+bip34 net height hash
+    | fst (getBip34Block net) == 0 = True
+    | fst (getBip34Block net) == height = snd (getBip34Block net) == hash
+    | otherwise = True
+
+-- | Check if the provided block height and version are valid.
+validVersion :: Network
+             -> BlockHeight  -- ^ new child height
+             -> Word32       -- ^ new child version
+             -> Bool
+validVersion net height version
+    | version < 2 = height < fst (getBip34Block net)
+    | version < 3 = height < getBip66Height net
+    | version < 4 = height < getBip65Height net
+    | otherwise = True
+
+-- | Find last block with normal, as opposed to minimum difficulty (for test
+-- networks).
+lastNoMinDiff :: BlockHeaders m => Network -> BlockNode -> m BlockNode
+lastNoMinDiff net bn@BlockNode {..} = do
+    let i = nodeHeight `mod` diffInterval net /= 0
+        c = encodeCompact (getPowLimit net)
+        l = blockBits nodeHeader == c
+        e1 =
+            error $
+            "Could not get block header for parent of " ++
+            show (headerHash nodeHeader)
+    if i && l
+        then do
+            bn' <- fromMaybe e1 <$> getBlockHeader (prevBlock nodeHeader)
+            lastNoMinDiff net bn'
+        else return bn
+
+lastNoMinDiff _ bn@GenesisNode{} = return bn
+
+-- | Returns the work required on a block header given the previous block. This
+-- coresponds to @bitcoind@ function @GetNextWorkRequired@ in @main.cpp@.
+nextWorkRequired :: BlockHeaders m
+                 => Network
+                 -> BlockNode
+                 -> BlockHeader
+                 -> m Word32
+nextWorkRequired net par bh = do
+    let mf = daa <|> eda <|> pow
+    case mf of
+        Just f -> f net par bh
+        Nothing ->
+            error
+                "Could not get an appropriate difficulty calculation algorithm"
+  where
+    daa = getDaaBlockHeight net >>= \daaHeight -> do
+        guard (nodeHeight par + 1 >= daaHeight)
+        return nextDaaWorkRequired
+    eda = getEdaBlockHeight net >>= \edaHeight -> do
+        guard (nodeHeight par + 1 >= edaHeight)
+        return nextEdaWorkRequired
+    pow = return nextPowWorkRequired
+
+-- | Find out the next amount of work required according to the Emergency
+-- Difficulty Adjustment (EDA) algorithm from Bitcoin Cash.
+nextEdaWorkRequired ::
+       BlockHeaders m => Network -> BlockNode -> BlockHeader -> m Word32
+nextEdaWorkRequired net par bh
+    | nodeHeight par + 1 `mod` diffInterval net == 0 =
+        nextWorkRequired net par bh
+    | minDifficulty = return (encodeCompact (getPowLimit net))
+    | blockBits (nodeHeader par) == encodeCompact (getPowLimit net) =
+        return (encodeCompact (getPowLimit net))
+    | otherwise = do
+        par6 <- fromMaybe e1 <$> getAncestor (nodeHeight par - 6) par
+        pars <- getParents 10 par
+        pars6 <- getParents 10 par6
+        let par6med =
+                medianTime $ map (blockTimestamp . nodeHeader) (par6 : pars6)
+            parmed = medianTime $ map (blockTimestamp . nodeHeader) (par : pars)
+            mtp6 = parmed - par6med
+        if mtp6 < 12 * 3600
+            then return $ blockBits (nodeHeader par)
+            else return $
+                 let (diff, _) = decodeCompact (blockBits (nodeHeader par))
+                     ndiff = diff + (diff `shiftR` 2)
+                  in if getPowLimit net > ndiff
+                         then encodeCompact (getPowLimit net)
+                         else encodeCompact ndiff
+  where
+    minDifficulty =
+        blockTimestamp bh >
+        blockTimestamp (nodeHeader par) + getTargetSpacing net * 2
+    e1 = error "Could not get seventh ancestor of block"
+
+-- | Find the next amount of work required according to the Difficulty
+-- Adjustment Algorithm (DAA) from Bitcoin Cash.
+nextDaaWorkRequired ::
+       BlockHeaders m => Network -> BlockNode -> BlockHeader -> m Word32
+nextDaaWorkRequired net par bh
+    | minDifficulty = return (encodeCompact (getPowLimit net))
+    | otherwise = do
+        let height = nodeHeight par
+        unless (height >= diffInterval net) $
+            error "Block height below difficulty interval"
+        l <- getSuitableBlock par
+        par144 <- fromMaybe e1 <$> getAncestor (height - 144) par
+        f <- getSuitableBlock par144
+        let nextTarget = computeTarget net f l
+        if nextTarget > getPowLimit net
+            then return $ encodeCompact (getPowLimit net)
+            else return $ encodeCompact nextTarget
+  where
+    e1 = error "Cannot get ancestor at parent - 144 height"
+    minDifficulty =
+        blockTimestamp bh >
+        blockTimestamp (nodeHeader par) + getTargetSpacing net * 2
+
+computeTarget :: Network -> BlockNode -> BlockNode -> Integer
+computeTarget net f l =
+    let work = (nodeWork l - nodeWork f) * fromIntegral (getTargetSpacing net)
+        actualTimespan =
+            blockTimestamp (nodeHeader l) - blockTimestamp (nodeHeader f)
+        actualTimespan'
+            | actualTimespan > 288 * getTargetSpacing net =
+                288 * getTargetSpacing net
+            | actualTimespan < 72 * getTargetSpacing net =
+                72 * getTargetSpacing net
+            | otherwise = actualTimespan
+        work' = work `div` fromIntegral actualTimespan'
+     in 2 ^ (256 :: Integer) `div` work'
+
+getSuitableBlock :: BlockHeaders m => BlockNode -> m BlockNode
+getSuitableBlock par = do
+    unless (nodeHeight par >= 3) $ error "Block height is less than three"
+    blocks <- (par :) <$> getParents 2 par
+    return $ sortBy (compare `on` blockTimestamp . nodeHeader) blocks !! 1
+
+-- | Returns the work required on a block header given the previous block. This
+-- coresponds to bitcoind function GetNextWorkRequired in main.cpp.
+nextPowWorkRequired ::
+       BlockHeaders m => Network -> BlockNode -> BlockHeader -> m Word32
+nextPowWorkRequired net par bh
+    | nodeHeight par + 1 `mod` diffInterval net /= 0 =
+        if getAllowMinDifficultyBlocks net
+            then if ht > pt + delta
+                     then return $ encodeCompact (getPowLimit net)
+                     else do
+                         d <- lastNoMinDiff net par
+                         return $ blockBits $ nodeHeader d
+            else return $ blockBits $ nodeHeader par
+    | otherwise = do
+        let rh = nodeHeight par - (diffInterval net - 1)
+        a <- fromMaybe e1 <$> getAncestor rh par
+        let t = blockTimestamp $ nodeHeader a
+        return $ calcNextWork net (nodeHeader par) t
+  where
+    e1 = error "Could not get ancestor for block header"
+    pt = blockTimestamp $ nodeHeader par
+    ht = blockTimestamp bh
+    delta = getTargetSpacing net * 2
+
+-- | Computes the work required for the first block in a new retarget period.
+calcNextWork :: Network
+             -> BlockHeader  -- ^ last block in previous retarget (parent)
+             -> Timestamp    -- ^ timestamp of first block in previous retarget
+             -> Word32
+calcNextWork net header time
+    | getPowNoRetargetting net = blockBits header
+    | new > getPowLimit net = encodeCompact (getPowLimit net)
+    | otherwise = encodeCompact new
+  where
+    s = blockTimestamp header - time
+    n | s < getTargetTimespan net `div` 4 = getTargetTimespan net `div` 4
+      | s > getTargetTimespan net * 4 = getTargetTimespan net * 4
+      | otherwise = s
+    l = fst $ decodeCompact $ blockBits header
+    new = l * fromIntegral n `div` fromIntegral (getTargetTimespan net)
+
+-- | Returns True if the difficulty target (bits) of the header is valid and the
+-- proof of work of the header matches the advertised difficulty target. This
+-- function corresponds to the function @CheckProofOfWork@ from @bitcoind@ in
+-- @main.cpp@.
+isValidPOW :: Network -> BlockHeader -> Bool
+isValidPOW net h
+    | target <= 0 || over || target > getPowLimit net = False
+    | otherwise = blockPOW (headerHash h) <= fromIntegral target
+  where
+    (target, over) = decodeCompact $ blockBits h
+
+-- | Returns the proof of work of a block header hash as an 'Integer' number.
+blockPOW :: BlockHash -> Integer
+blockPOW =  bsToInteger . B.reverse . encode
+
+-- | Returns the work represented by this block. Work is defined as the number
+-- of tries needed to solve a block in the average case with respect to the
+-- target.
+headerWork :: BlockHeader -> Integer
+headerWork bh = largestHash `div` (target + 1)
+  where
+    target      = fst $ decodeCompact $ blockBits bh
+    largestHash = 1 `shiftL` 256
+
+-- | Number of blocks on average between difficulty cycles (2016 blocks).
+diffInterval :: Network -> Word32
+diffInterval net = getTargetTimespan net `div` getTargetSpacing net
+
+-- | Compare two blocks to get the best.
+chooseBest :: BlockNode -> BlockNode -> BlockNode
+chooseBest b1 b2 | nodeWork b1 == nodeWork b2 =
+                       if nodeHeight b1 >= nodeHeight b2
+                       then b1
+                       else b2
+                 | nodeWork b1 > nodeWork b2 = b1
+                 | otherwise = b2
+
+-- | Get list of blocks for a block locator.
+blockLocatorNodes :: BlockHeaders m => BlockNode -> m [BlockNode]
+blockLocatorNodes best =
+    reverse <$> go [] best 1
+  where
+    e1 = error "Could not get ancestor"
+    go loc bn n =
+        let loc' = bn : loc
+            n' = if length loc' > 10
+                 then n * 2
+                 else 1
+        in if nodeHeight bn < n'
+           then do a <- fromMaybe e1 <$> getAncestor 0 bn
+                   return $ a : loc'
+           else do let h = nodeHeight bn - n'
+                   bn' <- fromMaybe e1 <$> getAncestor h bn
+                   go loc' bn' n'
+
+-- | Get block locator.
+blockLocator :: BlockHeaders m => BlockNode -> m BlockLocator
+blockLocator bn = map (headerHash . nodeHeader) <$> blockLocatorNodes bn
+
+-- | Become rich beyond your wildest dreams.
+mineBlock :: Network -> Word32 -> BlockHeader -> BlockHeader
+mineBlock net seed h =
+    head
+        [ j
+        | i <- (+ seed) <$> [0 .. maxBound]
+        , let j = h {bhNonce = i}
+        , isValidPOW net j
+        ]
+
+-- | Generate and append new blocks (mining). Only practical in regtest network.
+appendBlocks ::
+       Network
+    -> Word32 -- ^ random seed
+    -> BlockHeader
+    -> Int
+    -> [BlockHeader]
+appendBlocks _ _ _ 0 = []
+appendBlocks net seed bh i =
+    bh' : appendBlocks net seed bh' (i - 1)
+  where
+    bh' = mineBlock net seed bh
+        { prevBlock = headerHash bh
+          -- Just to make it different in every header
+        , merkleRoot = sha256 $ encode seed
+        }
+
+-- | Find the last common block ancestor between provided block headers.
+splitPoint :: BlockHeaders m => BlockNode -> BlockNode -> m BlockNode
+splitPoint l r = do
+    let h = min (nodeHeight l) (nodeHeight r)
+    ll <- fromMaybe e <$> getAncestor h l
+    lr <- fromMaybe e <$> getAncestor h r
+    f ll lr
+  where
+    e = error "BUG: Could not get ancestor at lowest height"
+    f ll lr =
+        if ll == lr
+            then return lr
+            else do
+                let h = nodeHeight ll - 1
+                pl <- fromMaybe e <$> getAncestor h ll
+                pr <- fromMaybe e <$> getAncestor h lr
+                f pl pr
+
+-- | Generate the entire Genesis block for 'Network'.
+genesisBlock :: Network -> Block
+genesisBlock net = Block (getGenesisHeader net) [genesisTx]
diff --git a/src/Network/Haskoin/Block/Merkle.hs b/src/Network/Haskoin/Block/Merkle.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Block/Merkle.hs
@@ -0,0 +1,244 @@
+module Network.Haskoin.Block.Merkle
+    ( MerkleBlock(..)
+    , MerkleRoot
+    , FlagBits
+    , PartialMerkleTree
+    , buildMerkleRoot
+    , merkleBlockTxs
+    , testMerkleRoot
+    -- * Helper functions
+    , buildPartialMerkle
+    , decodeMerkleFlags
+    , encodeMerkleFlags
+    , calcTreeHeight
+    , calcTreeWidth
+    , hash2
+    , calcHash
+    , traverseAndBuild
+    , traverseAndExtract
+    , extractMatches
+    , splitIn
+    , boolsToWord8
+    ) where
+
+import           Control.DeepSeq                   (NFData, rnf)
+import           Control.Monad                     (forM_, replicateM, when)
+import           Data.Bits
+import qualified Data.ByteString                   as BS
+import           Data.Either                       (isRight)
+import           Data.Maybe
+import           Data.Serialize                    (Serialize, encode, get, put)
+import           Data.Serialize.Get                (getWord32le, getWord8)
+import           Data.Serialize.Put                (putWord32le, putWord8)
+import           Data.Word                         (Word32, Word8)
+import           Network.Haskoin.Block.Common
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Network.Common
+import           Network.Haskoin.Transaction.Common
+
+-- | Hash of the block's Merkle root.
+type MerkleRoot        = Hash256
+
+-- | Bits that are used to rebuild partial merkle tree transaction hash list.
+type FlagBits          = [Bool]
+
+-- | Partial Merkle tree for a filtered block.
+type PartialMerkleTree = [Hash256]
+
+-- | Filtered block: a block with a partial Merkle tree that only includes the
+-- transactions that pass a bloom filter that was negotiated.
+data MerkleBlock =
+    MerkleBlock {
+                -- | block header
+                  merkleHeader    :: !BlockHeader
+                -- | total number of transactions in block
+                , merkleTotalTxns :: !Word32
+                -- | hashes in depth-first order
+                , mHashes         :: !PartialMerkleTree
+                -- | bits to rebuild partial merkle tree
+                , mFlags          :: !FlagBits
+                } deriving (Eq, Show)
+
+instance NFData MerkleBlock where
+    rnf (MerkleBlock m t h f) = rnf m `seq` rnf t `seq` rnf h `seq` rnf f
+
+instance Serialize MerkleBlock where
+
+    get = do
+        header <- get
+        ntx    <- getWord32le
+        (VarInt matchLen) <- get
+        hashes <- replicateM (fromIntegral matchLen) get
+        (VarInt flagLen)  <- get
+        ws <- replicateM (fromIntegral flagLen) getWord8
+        return $ MerkleBlock header ntx hashes (decodeMerkleFlags ws)
+
+    put (MerkleBlock h ntx hashes flags) = do
+        put h
+        putWord32le ntx
+        put $ VarInt $ fromIntegral $ length hashes
+        forM_ hashes put
+        let ws = encodeMerkleFlags flags
+        put $ VarInt $ fromIntegral $ length ws
+        forM_ ws putWord8
+
+-- | Unpack Merkle flags into 'FlagBits' structure.
+decodeMerkleFlags :: [Word8] -> FlagBits
+decodeMerkleFlags ws =
+    [ b | p <- [ 0 .. length ws * 8 - 1 ]
+        , b <- [ testBit (ws !! (p `div` 8)) (p `mod` 8) ]
+    ]
+
+-- | Pack Merkle flags from 'FlagBits'.
+encodeMerkleFlags :: FlagBits -> [Word8]
+encodeMerkleFlags bs = map boolsToWord8 $ splitIn 8 bs
+
+-- | Computes the height of a Merkle tree.
+calcTreeHeight :: Int -- ^ number of transactions (leaf nodes)
+               -> Int -- ^ height of the merkle tree
+calcTreeHeight ntx | ntx < 2 = 0
+                   | even ntx  = 1 + calcTreeHeight (ntx `div` 2)
+                   | otherwise = calcTreeHeight $ ntx + 1
+
+-- | Computes the width of a Merkle tree at a specific height. The transactions
+-- are at height 0.
+calcTreeWidth :: Int -- ^ number of transactions (leaf nodes)
+              -> Int -- ^ height at which we want to compute the width
+              -> Int -- ^ width of the Merkle tree
+calcTreeWidth ntx h = (ntx + (1 `shiftL` h) - 1) `shiftR` h
+
+-- | Computes the root of a Merkle tree from a list of leaf node hashes.
+buildMerkleRoot :: [TxHash]   -- ^ transaction hashes (leaf nodes)
+                -> MerkleRoot -- ^ root of the Merkle tree
+buildMerkleRoot txs = calcHash (calcTreeHeight $ length txs) 0 txs
+
+-- | Concatenate and compute double SHA256.
+hash2 :: Hash256 -> Hash256 -> Hash256
+hash2 a b = doubleSHA256 $ encode a `BS.append` encode b
+
+-- | Computes the hash of a specific node in a Merkle tree.
+calcHash :: Int       -- ^ height of the node
+         -> Int       -- ^ position of the node (0 for the leftmost node)
+         -> [TxHash]  -- ^ transaction hashes (leaf nodes)
+         -> Hash256   -- ^ hash of the node at the specified position
+calcHash height pos txs
+    | height < 0 || pos < 0 = error "calcHash: Invalid parameters"
+    | height == 0 = getTxHash $ txs !! pos
+    | otherwise = hash2 left right
+  where
+    left = calcHash (height-1) (pos*2) txs
+    right | pos*2+1 < calcTreeWidth (length txs) (height-1) =
+                calcHash (height-1) (pos*2+1) txs
+          | otherwise = left
+
+-- | Build a partial Merkle tree. Provide a list of tuples with all transaction
+-- hashes in the block, and whether the transaction is to be included in the
+-- partial tree. Returns a flag bits structure and the computed partial Merkle
+-- tree.
+buildPartialMerkle ::
+       [(TxHash, Bool)] -- ^ transaction hash and whether to include
+    -> (FlagBits, PartialMerkleTree) -- ^ flag bits and partial Merkle tree
+buildPartialMerkle hs = traverseAndBuild (calcTreeHeight $ length hs) 0 hs
+
+-- | Helper function to build partial Merkle tree. Used by 'buildPartialMerkle'
+-- above.
+traverseAndBuild ::
+       Int -> Int -> [(TxHash, Bool)] -> (FlagBits, PartialMerkleTree)
+traverseAndBuild height pos txs
+    | height < 0 || pos < 0 = error "traverseAndBuild: Invalid parameters"
+    | height == 0 || not match = ([match], [calcHash height pos t])
+    | otherwise = (match : lb ++ rb, lh ++ rh)
+  where
+    t = map fst txs
+    s = pos `shiftL` height
+    e = min (length txs) $ (pos + 1) `shiftL` height
+    match = any snd $ take (e - s) $ drop s txs
+    (lb, lh) = traverseAndBuild (height - 1) (pos * 2) txs
+    (rb, rh)
+        | (pos * 2 + 1) < calcTreeWidth (length txs) (height - 1) =
+            traverseAndBuild (height - 1) (pos * 2 + 1) txs
+        | otherwise = ([], [])
+
+-- | Helper function to extract transaction hashes from partial Merkle tree.
+traverseAndExtract :: Int -> Int -> Int -> FlagBits -> PartialMerkleTree
+                   -> Maybe (MerkleRoot, [TxHash], Int, Int)
+traverseAndExtract height pos ntx flags hashes
+    | null flags               = Nothing
+    | height == 0 || not match = leafResult
+    | isNothing leftM          = Nothing
+    | (pos*2+1) >= calcTreeWidth ntx (height-1) =
+        Just (hash2 lh lh, lm, lcf+1, lch)
+    | isNothing rightM         = Nothing
+    | otherwise =
+        Just (hash2 lh rh, lm ++ rm, lcf+rcf+1, lch+rch)
+  where
+    leafResult
+        | null hashes = Nothing
+        | otherwise = Just (h, [ TxHash h | height == 0 && match ], 1, 1)
+    (match:fs) = flags
+    (h:_)     = hashes
+    leftM  = traverseAndExtract (height-1) (pos*2) ntx fs hashes
+    (lh,lm,lcf,lch) = fromMaybe e leftM
+    rightM = traverseAndExtract (height-1) (pos*2+1) ntx
+                (drop lcf fs) (drop lch hashes)
+    (rh,rm,rcf,rch) = fromMaybe e rightM
+    e = error "traverseAndExtract: unexpected error extracting a Maybe value"
+
+-- | Extracts the matching hashes from a partial merkle tree. This will return
+-- the list of transaction hashes that have been included (set to true) in
+-- a call to 'buildPartialMerkle'.
+extractMatches :: Network
+               -> FlagBits
+               -> PartialMerkleTree
+               -> Int -- ^ number of transaction at height 0 (leaf nodes)
+               -> Either String (MerkleRoot, [TxHash])
+               -- ^ Merkle root and list of matching transaction hashes
+extractMatches net flags hashes ntx
+    | ntx == 0 = Left
+        "extractMatches: number of transactions can not be 0"
+    | ntx > getMaxBlockSize net `div` 60 = Left
+        "extractMatches: number of transactions excessively high"
+    | length hashes > ntx = Left
+        "extractMatches: More hashes provided than the number of transactions"
+    | length flags < length hashes = Left
+        "extractMatches: At least one bit per node and one bit per hash"
+    | isNothing resM = Left
+        "extractMatches: traverseAndExtract failed"
+    | (nBitsUsed+7) `div` 8 /= (length flags+7) `div` 8 = Left
+        "extractMatches: All bits were not consumed"
+    | nHashUsed /= length hashes = Left $
+        "extractMatches: All hashes were not consumed: " ++ show nHashUsed
+    | otherwise = return (merkRoot, matches)
+  where
+    resM = traverseAndExtract (calcTreeHeight ntx) 0 ntx flags hashes
+    (merkRoot, matches, nBitsUsed, nHashUsed) = fromMaybe e resM
+    e = error "extractMatches: unexpected error extracting a Maybe value"
+
+-- | Helper function to split a list in chunks 'Int' length. Last chunk may be
+-- smaller.
+splitIn :: Int -> [a] -> [[a]]
+splitIn _ [] = []
+splitIn c xs = xs1 : splitIn c xs2
+  where
+    (xs1, xs2) = splitAt c xs
+
+-- | Pack up to eight bools in a byte.
+boolsToWord8 :: [Bool] -> Word8
+boolsToWord8 [] = 0
+boolsToWord8 xs = foldl setBit 0 (map snd $ filter fst $ zip xs [0..7])
+
+-- | Get matching transactions from Merkle block.
+merkleBlockTxs :: Network -> MerkleBlock -> Either String [TxHash]
+merkleBlockTxs net b =
+    let flags = mFlags b
+        hs = mHashes b
+        n = fromIntegral $ merkleTotalTxns b
+        merkle = merkleRoot $ merkleHeader b
+    in do (root, ths) <- extractMatches net flags hs n
+          when (root /= merkle) $ Left "merkleBlockTxs: Merkle root incorrect"
+          return ths
+
+-- | Check if Merkle block root is valid against the block header.
+testMerkleRoot :: Network -> MerkleBlock -> Bool
+testMerkleRoot net = isRight . merkleBlockTxs net
diff --git a/src/Network/Haskoin/Constants.hs b/src/Network/Haskoin/Constants.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Constants.hs
@@ -0,0 +1,503 @@
+{-# LANGUAGE DeriveGeneric     #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Constants
+    ( Network(..)
+    , btc
+    , btcTest
+    , btcRegTest
+    , bch
+    , bchTest
+    , bchRegTest
+    , allNets
+    , netByName
+    , netByIdent
+    ) where
+
+import           Control.DeepSeq
+import           Data.ByteString             (ByteString)
+import           Data.List
+import           Data.Maybe
+import           Data.String
+import           Data.Text                    (Text)
+import           Data.Version
+import           Data.Word                    (Word32, Word64, Word8)
+import           GHC.Generics                 (Generic)
+import           Network.Haskoin.Block.Common
+import           Paths_haskoin_core
+import           Text.Read
+
+-- | Version of Haskoin Core package.
+versionString :: IsString a => a
+versionString = fromString (showVersion version)
+
+-- | Constants for network.
+data Network = Network
+    { -- | lowercase alphanumeric and dashes
+      getNetworkName              :: !String
+      -- | network Haskell identifier
+    , getNetworkIdent             :: !String
+      -- | prefix for 'Base58' P2PKH addresses
+    , getAddrPrefix               :: !Word8
+      -- | prefix for 'Base58' P2SH addresses
+    , getScriptPrefix             :: !Word8
+      -- | prefix for WIF private key
+    , getSecretPrefix             :: !Word8
+      -- | prefix for extended public key
+    , getExtPubKeyPrefix          :: !Word32
+      -- | prefix for extended private key
+    , getExtSecretPrefix          :: !Word32
+      -- | network magic
+    , getNetworkMagic             :: !Word32
+      -- | genesis block header
+    , getGenesisHeader            :: !BlockHeader
+      -- | maximum block size in bytes
+    , getMaxBlockSize             :: !Int
+      -- | maximum amount of satoshi
+    , getMaxSatoshi               :: !Word64
+      -- | user agent string
+    , getHaskoinUserAgent         :: !ByteString
+      -- | default port for P2P connections
+    , getDefaultPort              :: !Int
+      -- | allow min difficulty blocks (testnet)
+    , getAllowMinDifficultyBlocks :: !Bool
+      -- | do not retarget difficulty (regtest)
+    , getPowNoRetargetting        :: !Bool
+      -- | proof-of-work target higest possible value
+    , getPowLimit                 :: !Integer
+      -- | block at which BIP34 activates
+    , getBip34Block               :: !(BlockHeight, BlockHash)
+      -- | block at which BIP65 activates
+    , getBip65Height              :: !BlockHeight
+      -- | block at which BIP66 activates
+    , getBip66Height              :: !BlockHeight
+      -- | time between difficulty retargets
+    , getTargetTimespan           :: !Word32
+      -- | time between blocks
+    , getTargetSpacing            :: !Word32
+      -- | checkpoints
+    , getCheckpoints              :: ![(BlockHeight, BlockHash)]
+      -- | BIP44 derivation path root
+    , getBip44Coin                :: !Word32
+      -- | peer-to-peer network seeds
+    , getSeeds                    :: ![String]
+      -- | fork id for replay protection
+    , getSigHashForkId            :: !(Maybe Word32)
+      -- | EDA start block height
+    , getEdaBlockHeight           :: !(Maybe Word32)
+      -- | DAA start block height
+    , getDaaBlockHeight           :: !(Maybe Word32)
+      -- | segregated witness active
+    , getSegWit                   :: !Bool
+      -- | 'CashAddr' prefix (for Bitcoin Cash)
+    , getCashAddrPrefix           :: !(Maybe Text)
+      -- | 'Bech32' prefix (for SegWit network)
+    , getBech32Prefix             :: !(Maybe Text)
+    } deriving (Eq, Generic)
+
+instance NFData Network
+
+instance Show Network where
+    show = getNetworkIdent
+
+instance Read Network where
+    readPrec = do
+        Ident str <- lexP
+        maybe pfail return (netByIdent str)
+
+instance IsString Network where
+    fromString = fromMaybe (error "Network name invalid") . netByName
+
+-- | Query known networks by name.
+netByName :: String -> Maybe Network
+netByName str = find ((== str) . getNetworkName) allNets
+
+-- | Query known networks by Haskell identifier.
+netByIdent :: String -> Maybe Network
+netByIdent str = find ((== str) . getNetworkIdent) allNets
+
+-- | Bitcoin SegWit network. Symbol: BTC.
+btc :: Network
+btc =
+    Network
+    { getNetworkName = "btc"
+    , getNetworkIdent = "btc"
+    , getAddrPrefix = 0
+    , getScriptPrefix = 5
+    , getSecretPrefix = 128
+    , getExtPubKeyPrefix = 0x0488b21e
+    , getExtSecretPrefix = 0x0488ade4
+    , getNetworkMagic = 0xf9beb4d9
+    , getGenesisHeader =
+          BlockHeader
+              0x01
+              "0000000000000000000000000000000000000000000000000000000000000000"
+              "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"
+              1231006505
+              0x1d00ffff
+              2083236893
+            -- Hash 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
+    , getMaxBlockSize = 1000000
+    , getMaxSatoshi = 2100000000000000
+    , getHaskoinUserAgent =
+          "/haskoin-btc:" <> versionString <> "/"
+    , getDefaultPort = 8333
+    , getAllowMinDifficultyBlocks = False
+    , getPowNoRetargetting = False
+    , getPowLimit =
+          0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+    , getBip34Block =
+          ( 227931
+          , "000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8")
+    , getBip65Height = 388381
+    , getBip66Height = 363725
+    , getTargetTimespan = 14 * 24 * 60 * 60
+    , getTargetSpacing = 10 * 60
+    , getCheckpoints =
+          [ ( 11111
+            , "0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")
+          , ( 33333
+            , "000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")
+          , ( 74000
+            , "0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")
+          , ( 105000
+            , "00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")
+          , ( 134444
+            , "00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")
+          , ( 168000
+            , "000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")
+          , ( 193000
+            , "000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")
+          , ( 210000
+            , "000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")
+          , ( 216116
+            , "00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")
+          , ( 225430
+            , "00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")
+          , ( 250000
+            , "000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")
+          , ( 279000
+            , "0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")
+          , ( 295000
+            , "00000000000000004d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983")
+          ]
+    , getSeeds =
+          [ "seed.bitcoin.sipa.be" -- Pieter Wuille
+          , "dnsseed.bluematt.me" -- Matt Corallo
+          , "dnsseed.bitcoin.dashjr.org" -- Luke Dashjr
+          , "seed.bitcoinstats.com" -- Chris Decker
+          , "seed.bitcoin.jonasschnelli.ch" -- Jonas Schnelli
+          , "seed.btc.petertodd.org" -- Peter Todd
+          , "seed.bitcoin.sprovoost.nl" -- Sjors Provoost
+          ]
+    , getBip44Coin = 0
+    , getSigHashForkId = Nothing
+    , getEdaBlockHeight = Nothing
+    , getDaaBlockHeight = Nothing
+    , getSegWit = True
+    , getCashAddrPrefix = Nothing
+    , getBech32Prefix = Just "bc"
+    }
+
+-- | Testnet for Bitcoin SegWit network.
+btcTest :: Network
+btcTest =
+    Network
+    { getNetworkName = "btctest"
+    , getNetworkIdent = "btcTest"
+    , getAddrPrefix = 111
+    , getScriptPrefix = 196
+    , getSecretPrefix = 239
+    , getExtPubKeyPrefix = 0x043587cf
+    , getExtSecretPrefix = 0x04358394
+    , getNetworkMagic = 0x0b110907
+    , getGenesisHeader =
+          BlockHeader
+              0x01
+              "0000000000000000000000000000000000000000000000000000000000000000"
+              "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"
+              1296688602
+              486604799
+              414098458
+            -- Hash 000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943
+    , getMaxBlockSize = 1000000
+    , getMaxSatoshi = 2100000000000000
+    , getHaskoinUserAgent = "/haskoin-btc-test:" <> versionString <> "/"
+    , getDefaultPort = 18333
+    , getAllowMinDifficultyBlocks = True
+    , getPowNoRetargetting = False
+    , getPowLimit =
+          0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+    , getBip34Block =
+          ( 21111
+          , "0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8")
+    , getBip65Height = 581885
+    , getBip66Height = 330776
+    , getTargetTimespan = 14 * 24 * 60 * 60
+    , getTargetSpacing = 10 * 60
+    , getCheckpoints =
+          [ ( 546
+            , "000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")
+          ]
+    , getSeeds =
+          [ "testnet-seed.bitcoin.jonasschnelli.ch"
+          , "seed.tbtc.petertodd.org"
+          , "seed.testnet.bitcoin.sprovoost.nl"
+          , "testnet-seed.bluematt.me"
+          ]
+    , getBip44Coin = 1
+    , getSigHashForkId = Nothing
+    , getEdaBlockHeight = Nothing
+    , getDaaBlockHeight = Nothing
+    , getSegWit = True
+    , getCashAddrPrefix = Nothing
+    , getBech32Prefix = Just "tb"
+    }
+
+-- | RegTest for Bitcoin SegWit network.
+btcRegTest :: Network
+btcRegTest =
+    Network
+    { getNetworkName = "btcreg"
+    , getNetworkIdent = "btcRegTest"
+    , getAddrPrefix = 111
+    , getScriptPrefix = 196
+    , getSecretPrefix = 239
+    , getExtPubKeyPrefix = 0x043587cf
+    , getExtSecretPrefix = 0x04358394
+    , getNetworkMagic = 0xfabfb5da
+    , getGenesisHeader =
+          BlockHeader
+           -- 0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206
+              0x01
+              "0000000000000000000000000000000000000000000000000000000000000000"
+              "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"
+              1296688602
+              0x207fffff
+              2
+    , getMaxBlockSize = 1000000
+    , getMaxSatoshi = 2100000000000000
+    , getHaskoinUserAgent = "/haskoin-btc-regtest:" <> versionString <> "/"
+    , getDefaultPort = 18444
+    , getAllowMinDifficultyBlocks = True
+    , getPowNoRetargetting = True
+    , getPowLimit =
+          0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+    , getBip34Block =
+          ( 100000000
+          , "0000000000000000000000000000000000000000000000000000000000000000")
+    , getBip65Height = 1351
+    , getBip66Height = 1251
+    , getTargetTimespan = 14 * 24 * 60 * 60
+    , getTargetSpacing = 10 * 60
+    , getCheckpoints = []
+    , getSeeds = ["localhost"]
+    , getBip44Coin = 1
+    , getSigHashForkId = Nothing
+    , getEdaBlockHeight = Nothing
+    , getDaaBlockHeight = Nothing
+    , getSegWit = True
+    , getCashAddrPrefix = Nothing
+    , getBech32Prefix = Just "bcrt"
+    }
+
+-- | Bitcoin Cash network. Symbol: BCH.
+bch :: Network
+bch =
+    Network
+    { getNetworkName = "bch"
+    , getNetworkIdent = "bch"
+    , getAddrPrefix = 0
+    , getScriptPrefix = 5
+    , getSecretPrefix = 128
+    , getExtPubKeyPrefix = 0x0488b21e
+    , getExtSecretPrefix = 0x0488ade4
+    , getNetworkMagic = 0xe3e1f3e8
+    , getGenesisHeader =
+          BlockHeader
+              0x01
+              "0000000000000000000000000000000000000000000000000000000000000000"
+              "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"
+              1231006505
+              0x1d00ffff
+              2083236893
+            -- Hash 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
+    , getMaxBlockSize = 32000000
+    , getMaxSatoshi = 2100000000000000
+    , getHaskoinUserAgent = "/haskoin-bch:" <> versionString <> "/"
+    , getDefaultPort = 8333
+    , getAllowMinDifficultyBlocks = False
+    , getPowNoRetargetting = False
+    , getPowLimit =
+          0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+    , getBip34Block =
+          ( 227931
+          , "000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8")
+    , getBip65Height = 388381
+    , getBip66Height = 363725
+    , getTargetTimespan = 14 * 24 * 60 * 60
+    , getTargetSpacing = 10 * 60
+    , getCheckpoints =
+          [ ( 11111
+            , "0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")
+          , ( 33333
+            , "000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")
+          , ( 74000
+            , "0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")
+          , ( 105000
+            , "00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")
+          , ( 134444
+            , "00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")
+          , ( 168000
+            , "000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")
+          , ( 193000
+            , "000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")
+          , ( 210000
+            , "000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")
+          , ( 216116
+            , "00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")
+          , ( 225430
+            , "00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")
+          , ( 250000
+            , "000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")
+          , ( 279000
+            , "0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")
+          , ( 295000
+            , "00000000000000004d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983")
+            -- UAHF fork block.
+          , ( 478559
+            , "000000000000000000651ef99cb9fcbe0dadde1d424bd9f15ff20136191a5eec")
+            -- Nov, 13 DAA activation block.
+          , ( 504031
+            , "0000000000000000011ebf65b60d0a3de80b8175be709d653b4c1a1beeb6ab9c")
+          ]
+    , getSeeds =
+          [ "seed.bitcoinabc.org"
+          , "seed-abc.bitcoinforks.org"
+          , "btccash-seeder.bitcoinunlimited.info"
+          , "seed.bitprim.org"
+          , "seed.deadalnix.me"
+          , "seeder.criptolayer.net"
+          ]
+    , getBip44Coin = 145
+    , getSigHashForkId = Just 0
+    , getEdaBlockHeight = Just 478559
+    , getDaaBlockHeight = Just 404031
+    , getSegWit = False
+    , getCashAddrPrefix = Just "bitcoincash"
+    , getBech32Prefix = Nothing
+    }
+
+-- | Testnet for Bitcoin Cash network.
+bchTest :: Network
+bchTest =
+    Network
+    { getNetworkName = "bchtest"
+    , getNetworkIdent = "bchTest"
+    , getAddrPrefix = 111
+    , getScriptPrefix = 196
+    , getSecretPrefix = 239
+    , getExtPubKeyPrefix = 0x043587cf
+    , getExtSecretPrefix = 0x04358394
+    , getNetworkMagic = 0xf4e5f3f4
+    , getGenesisHeader =
+          BlockHeader
+              0x01
+              "0000000000000000000000000000000000000000000000000000000000000000"
+              "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"
+              1296688602
+              486604799
+              414098458
+            -- Hash 000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943
+    , getMaxBlockSize = 32000000
+    , getMaxSatoshi = 2100000000000000
+    , getHaskoinUserAgent = "/haskoin-bch-test:" <> versionString <> "/"
+    , getDefaultPort = 18333
+    , getAllowMinDifficultyBlocks = True
+    , getPowNoRetargetting = False
+    , getPowLimit =
+          0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+    , getBip34Block =
+          ( 21111
+          , "0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8")
+    , getBip65Height = 581885
+    , getBip66Height = 330776
+    , getTargetTimespan = 14 * 24 * 60 * 60
+    , getTargetSpacing = 10 * 60
+    , getCheckpoints =
+          [ ( 546
+            , "000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")
+            -- UAHF fork block.
+          , ( 1155876
+            , "00000000000e38fef93ed9582a7df43815d5c2ba9fd37ef70c9a0ea4a285b8f5")
+            -- Nov, 13. DAA activation block.
+          , ( 1188697
+            , "0000000000170ed0918077bde7b4d36cc4c91be69fa09211f748240dabe047fb")
+          ]
+    , getSeeds =
+          [ "testnet-seed.bitcoinabc.org"
+          , "testnet-seed-abc.bitcoinforks.org"
+          , "testnet-seed.bitprim.org"
+          , "testnet-seed.deadalnix.me"
+          , "testnet-seeder.criptolayer.net"
+          ]
+    , getBip44Coin = 1
+    , getSigHashForkId = Just 0
+    , getEdaBlockHeight = Just 1155876
+    , getDaaBlockHeight = Just 1188697
+    , getSegWit = False
+    , getCashAddrPrefix = Just "bchtest"
+    , getBech32Prefix = Nothing
+    }
+
+-- | RegTest for Bitcoin Cash network.
+bchRegTest :: Network
+bchRegTest =
+    Network
+    { getNetworkName = "bchreg"
+    , getNetworkIdent = "bchRegTest"
+    , getAddrPrefix = 111
+    , getScriptPrefix = 196
+    , getSecretPrefix = 239
+    , getExtPubKeyPrefix = 0x043587cf
+    , getExtSecretPrefix = 0x04358394
+    , getNetworkMagic = 0xdab5bffa
+    , getGenesisHeader =
+          BlockHeader
+           -- 0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206
+              0x01
+              "0000000000000000000000000000000000000000000000000000000000000000"
+              "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"
+              1296688602
+              0x207fffff
+              2
+    , getMaxBlockSize = 1000000
+    , getMaxSatoshi = 2100000000000000
+    , getHaskoinUserAgent = "/haskoin-bch-regtest:" <> versionString <> "/"
+    , getDefaultPort = 18444
+    , getAllowMinDifficultyBlocks = True
+    , getPowNoRetargetting = True
+    , getPowLimit =
+          0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+    , getBip34Block =
+          ( 100000000
+          , "0000000000000000000000000000000000000000000000000000000000000000")
+    , getBip65Height = 1351
+    , getBip66Height = 1251
+    , getTargetTimespan = 14 * 24 * 60 * 60
+    , getTargetSpacing = 10 * 60
+    , getCheckpoints =
+          [ ( 0
+            , "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")
+          ]
+    , getSeeds = ["localhost"]
+    , getBip44Coin = 1
+    , getSigHashForkId = Just 0
+    , getEdaBlockHeight = Nothing
+    , getDaaBlockHeight = Just 0
+    , getSegWit = False
+    , getCashAddrPrefix = Just "bchreg"
+    , getBech32Prefix = Nothing
+    }
+
+allNets :: [Network]
+allNets = [btc, bch, btcTest, bchTest, btcRegTest, bchRegTest]
diff --git a/src/Network/Haskoin/Crypto.hs b/src/Network/Haskoin/Crypto.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Crypto.hs
@@ -0,0 +1,6 @@
+module Network.Haskoin.Crypto
+    ( module X
+    ) where
+
+import           Network.Haskoin.Crypto.Hash      as X
+import           Network.Haskoin.Crypto.Signature as X
diff --git a/src/Network/Haskoin/Crypto/Hash.hs b/src/Network/Haskoin/Crypto/Hash.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Crypto/Hash.hs
@@ -0,0 +1,189 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module Network.Haskoin.Crypto.Hash
+    ( -- * Hashes
+      Hash512(getHash512)
+    , Hash256(getHash256)
+    , Hash160(getHash160)
+    , CheckSum32(getCheckSum32)
+    , sha512
+    , sha256
+    , ripemd160
+    , sha1
+    , doubleSHA256
+    , addressHash
+    , checkSum32
+    , hmac512
+    , hmac256
+    , split512
+    , join512
+    ) where
+
+import           Control.DeepSeq         (NFData)
+import           Crypto.Hash             (RIPEMD160 (..), SHA1 (..),
+                                          SHA256 (..), SHA512 (..), hashWith)
+import           Crypto.MAC.HMAC         (HMAC, hmac)
+import           Data.ByteArray          (ByteArrayAccess)
+import qualified Data.ByteArray          as BA
+import           Data.ByteString         (ByteString)
+import qualified Data.ByteString         as BS
+import           Data.ByteString.Short   (ShortByteString)
+import qualified Data.ByteString.Short   as BSS
+import           Data.Either             (fromRight)
+import           Data.Hashable           (Hashable)
+import           Data.Serialize          (Serialize (..), decode)
+import qualified Data.Serialize.Get      as Get
+import qualified Data.Serialize.Put      as Put
+import           Data.String             (IsString, fromString)
+import           Data.String.Conversions (cs)
+import           Data.Word               (Word32)
+import           Network.Haskoin.Util
+import           Text.Read               as R
+
+-- | 'Word32' wrapped for type-safe 32-bit checksums.
+newtype CheckSum32 = CheckSum32
+    { getCheckSum32 :: Word32
+    } deriving (Eq, Ord, Serialize, NFData, Show, Read, Hashable)
+
+-- | Type for 512-bit hashes.
+newtype Hash512 = Hash512 { getHash512 :: ShortByteString }
+    deriving (Eq, Ord, NFData, Hashable)
+
+-- | Type for 256-bit hashes.
+newtype Hash256 = Hash256 { getHash256 :: ShortByteString }
+    deriving (Eq, Ord, NFData, Hashable)
+
+-- | Type for 160-bit hashes.
+newtype Hash160 = Hash160 { getHash160 :: ShortByteString }
+    deriving (Eq, Ord, NFData, Hashable)
+
+instance Show Hash512 where
+    showsPrec _ = shows . encodeHex . BSS.fromShort . getHash512
+
+instance Read Hash512 where
+    readPrec = do
+        R.String str <- lexP
+        maybe pfail return $ Hash512 . BSS.toShort <$> decodeHex (cs str)
+
+instance Show Hash256 where
+    showsPrec _ = shows . encodeHex . BSS.fromShort . getHash256
+
+instance Read Hash256 where
+    readPrec = do
+        R.String str <- lexP
+        maybe pfail return $ Hash256 . BSS.toShort <$> decodeHex (cs str)
+
+instance Show Hash160 where
+    showsPrec _ = shows . encodeHex . BSS.fromShort . getHash160
+
+instance Read Hash160 where
+    readPrec = do
+        R.String str <- lexP
+        maybe pfail return $ Hash160 . BSS.toShort <$> decodeHex (cs str)
+
+instance IsString Hash512 where
+    fromString str =
+        case decodeHex $ cs str of
+            Nothing -> e
+            Just bs ->
+                case BS.length bs of
+                    64 -> Hash512 (BSS.toShort bs)
+                    _  -> e
+      where
+        e = error "Could not decode hash from hex string"
+
+instance Serialize Hash512 where
+    get = Hash512 <$> Get.getShortByteString 64
+    put = Put.putShortByteString . getHash512
+
+instance IsString Hash256 where
+    fromString str =
+        case decodeHex $ cs str of
+            Nothing -> e
+            Just bs ->
+                case BS.length bs of
+                    32 -> Hash256 (BSS.toShort bs)
+                    _  -> e
+      where
+        e = error "Could not decode hash from hex string"
+
+instance Serialize Hash256 where
+    get = Hash256 <$> Get.getShortByteString 32
+    put = Put.putShortByteString . getHash256
+
+instance IsString Hash160 where
+    fromString str =
+        case decodeHex $ cs str of
+            Nothing -> e
+            Just bs ->
+                case BS.length bs of
+                    20 -> Hash160 (BSS.toShort bs)
+                    _  -> e
+      where
+        e = error "Could not decode hash from hex string"
+
+instance Serialize Hash160 where
+    get = Hash160 <$> Get.getShortByteString 20
+    put = Put.putShortByteString . getHash160
+
+-- | Calculate SHA512 hash.
+sha512 :: ByteArrayAccess b => b -> Hash512
+sha512 = Hash512 . BSS.toShort . BA.convert . hashWith SHA512
+
+-- | Calculate SHA256 hash.
+sha256 :: ByteArrayAccess b => b -> Hash256
+sha256 = Hash256 . BSS.toShort . BA.convert . hashWith SHA256
+
+-- | Calculate RIPEMD160 hash.
+ripemd160 :: ByteArrayAccess b => b -> Hash160
+ripemd160 = Hash160 . BSS.toShort . BA.convert. hashWith RIPEMD160
+
+-- | Claculate SHA1 hash.
+sha1 :: ByteArrayAccess b => b -> Hash160
+sha1 = Hash160 . BSS.toShort . BA.convert . hashWith SHA1
+
+-- | Compute two rounds of SHA-256.
+doubleSHA256 :: ByteArrayAccess b => b -> Hash256
+doubleSHA256 =
+    Hash256 . BSS.toShort . BA.convert . hashWith SHA256 . hashWith SHA256
+
+-- | Compute SHA-256 followed by RIPMED-160.
+addressHash :: ByteArrayAccess b => b -> Hash160
+addressHash =
+    Hash160 . BSS.toShort . BA.convert . hashWith RIPEMD160 . hashWith SHA256
+
+{- CheckSum -}
+
+-- | Computes a 32 bit checksum.
+checkSum32 :: ByteArrayAccess b => b -> CheckSum32
+checkSum32 = fromRight (error "Colud not decode bytes as CheckSum32")
+             . decode
+             . BS.take 4
+             . BA.convert
+             . hashWith SHA256
+             . hashWith SHA256
+
+{- HMAC -}
+
+-- | Computes HMAC over SHA-512.
+hmac512 :: ByteString -> ByteString -> Hash512
+hmac512 key msg =
+    Hash512 $ BSS.toShort $ BA.convert (hmac key msg :: HMAC SHA512)
+
+-- | Computes HMAC over SHA-256.
+hmac256 :: (ByteArrayAccess k, ByteArrayAccess m) => k -> m -> Hash256
+hmac256 key msg =
+    Hash256 $ BSS.toShort $ BA.convert (hmac key msg :: HMAC SHA256)
+
+-- | Split a 'Hash512' into a pair of 'Hash256'.
+split512 :: Hash512 -> (Hash256, Hash256)
+split512 h =
+    (Hash256 (BSS.toShort a), Hash256 (BSS.toShort b))
+  where
+    (a, b) = BS.splitAt 32 . BSS.fromShort $ getHash512 h
+
+-- | Join a pair of 'Hash256' into a 'Hash512'.
+join512 :: (Hash256, Hash256) -> Hash512
+join512 (a, b) =
+    Hash512 .
+    BSS.toShort $
+        BSS.fromShort (getHash256 a) `BS.append` BSS.fromShort (getHash256 b)
diff --git a/src/Network/Haskoin/Crypto/Signature.hs b/src/Network/Haskoin/Crypto/Signature.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Crypto/Signature.hs
@@ -0,0 +1,82 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Crypto.Signature
+    ( -- * Signatures
+      Sig
+    , putSig
+    , getSig
+    , signHash
+    , verifyHashSig
+    , isCanonicalHalfOrder
+    , decodeStrictSig
+    , exportSig
+    , exportCompactSig
+    ) where
+
+import           Control.Monad               (guard, unless, when)
+import           Crypto.Secp256k1
+import           Data.ByteString             (ByteString)
+import qualified Data.ByteString             as BS
+import           Data.ByteString.Short       (toShort)
+import           Data.Maybe                  (fromMaybe)
+import           Data.Serialize              as S
+import           Data.Serialize.Put          (Putter, putByteString)
+import           Network.Haskoin.Crypto.Hash
+import           Numeric                     (showHex)
+
+-- | Convert 256-bit hash into a 'Msg' for signing or verification.
+hashToMsg :: Hash256 -> Msg
+hashToMsg =
+    fromMaybe e . msg . encode
+  where
+    e = error "Could not convert 32-byte hash to secp256k1 message"
+
+-- | Sign a 256-bit hash using secp256k1 elliptic curve.
+signHash :: SecKey -> Hash256 -> Sig
+signHash k = signMsg k . hashToMsg
+
+-- | Verify an ECDSA signature for a 256-bit hash.
+verifyHashSig :: Hash256 -> Sig -> PubKey -> Bool
+verifyHashSig h s p =
+    verifySig p g m
+  where
+    (g, _) = normalizeSig s
+    m = hashToMsg h
+
+-- | Deserialize an ECDSA signature as commonly encoded in Bitcoin.
+getSig :: Get Sig
+getSig = do
+        l <- lookAhead $ do
+            t <- getWord8
+            -- 0x30 is DER sequence type
+            unless (t == 0x30) $ fail $
+                "Bad DER identifier byte 0x" ++ showHex t ". Expecting 0x30"
+            l <- getWord8
+            when (l == 0x00) $ fail "Indeterminate form unsupported"
+            when (l >= 0x80) $ fail "Multi-octect length not supported"
+            return $ fromIntegral l
+        bs <- getByteString $ l + 2
+        case decodeStrictSig bs of
+            Just s  -> return s
+            Nothing -> fail "Invalid signature"
+
+-- | Serialize an ECDSA signatur for Bitcoin use.
+putSig :: Putter Sig
+putSig s = putByteString $ exportSig s
+
+-- | Is canonical half order.
+isCanonicalHalfOrder :: Sig -> Bool
+isCanonicalHalfOrder = not . snd . normalizeSig
+
+-- | Decode signature strictly.
+decodeStrictSig :: ByteString -> Maybe Sig
+decodeStrictSig bs = do
+    g <- importSig bs
+    let compact = exportCompactSig g
+    -- <http://www.secg.org/sec1-v2.pdf Section 4.1.4>
+    -- 4.1.4.1 (r and s can not be zero)
+    guard $ getCompactSigR compact /= zero
+    guard $ getCompactSigS compact /= zero
+    guard $ isCanonicalHalfOrder g
+    return g
+  where
+    zero = toShort $ BS.replicate 32 0
diff --git a/src/Network/Haskoin/Keys.hs b/src/Network/Haskoin/Keys.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Keys.hs
@@ -0,0 +1,7 @@
+module Network.Haskoin.Keys
+    ( module X
+    ) where
+
+import           Network.Haskoin.Keys.Common   as X
+import           Network.Haskoin.Keys.Extended as X
+import           Network.Haskoin.Keys.Mnemonic as X
diff --git a/src/Network/Haskoin/Keys/Common.hs b/src/Network/Haskoin/Keys/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Keys/Common.hs
@@ -0,0 +1,138 @@
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Keys.Common
+    ( -- * Public & Private Keys
+      PubKeyI(..)
+    , SecKeyI(..)
+    , PubKey
+    , SecKey
+    , exportPubKey
+    , importPubKey
+    , wrapPubKey
+    , derivePubKey
+    , derivePubKeyI
+    , wrapSecKey
+    , fromMiniKey
+    , tweakPubKey
+    , tweakSecKey
+    , secKeyPut
+    , secKeyGet
+    , getSecKey
+    , secKey
+    ) where
+
+import           Control.Applicative         ((<|>))
+import           Control.DeepSeq             (NFData, rnf)
+import           Control.Monad               (guard, mzero, (<=<))
+import           Crypto.Secp256k1
+import           Data.Aeson                  (FromJSON, ToJSON, Value (String),
+                                              parseJSON, toJSON, withText)
+import           Data.ByteString             (ByteString)
+import qualified Data.ByteString             as BS
+import           Data.Maybe                  (fromMaybe)
+import           Data.Serialize              (Serialize, decode, encode, get,
+                                              put)
+import           Data.Serialize.Get          (Get, getByteString)
+import           Data.Serialize.Put          (Putter, putByteString)
+import           Data.String                 (IsString, fromString)
+import           Data.String.Conversions     (cs)
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Util
+import           Text.Read                   (lexP, parens, pfail, readPrec)
+import qualified Text.Read                   as Read
+
+-- | Elliptic curve public key type with expected serialized compression flag.
+data PubKeyI = PubKeyI
+    { pubKeyPoint      :: !PubKey
+    , pubKeyCompressed :: !Bool
+    } deriving (Eq)
+
+instance Show PubKeyI where
+    showsPrec _ = shows . encodeHex . encode
+
+instance Read PubKeyI where
+    readPrec = parens $ do
+        Read.String str <- lexP
+        maybe pfail return $ eitherToMaybe . decode <=< decodeHex $ cs str
+
+instance IsString PubKeyI where
+    fromString str =
+        fromMaybe e $ eitherToMaybe . decode <=< decodeHex $ cs str
+      where
+        e = error "Could not decode public key"
+
+instance NFData PubKeyI where
+    rnf (PubKeyI p c) = p `seq` rnf c `seq` rnf ()
+
+instance ToJSON PubKeyI where
+    toJSON = String . encodeHex . encode
+
+instance FromJSON PubKeyI where
+    parseJSON = withText "PubKeyI" $
+        maybe mzero return . (eitherToMaybe . decode =<<) . decodeHex
+
+instance Serialize PubKeyI where
+    get = c <|> u
+      where
+        c = do
+            bs <- getByteString 33
+            guard $ BS.head bs `BS.elem` BS.pack [0x02, 0x03]
+            maybe mzero return $ PubKeyI <$> importPubKey bs <*> pure True
+        u = do
+            bs <- getByteString 65
+            guard $ BS.head bs == 0x04
+            maybe mzero return $ PubKeyI <$> importPubKey bs <*> pure False
+
+    put pk = putByteString $ exportPubKey (pubKeyCompressed pk) (pubKeyPoint pk)
+
+-- | Wrap a public key from secp256k1 library adding information about compression.
+wrapPubKey :: Bool -> PubKey -> PubKeyI
+wrapPubKey c p = PubKeyI p c
+
+-- | Derives a public key from a private key. This function will preserve
+-- compression flag.
+derivePubKeyI :: SecKeyI -> PubKeyI
+derivePubKeyI (SecKeyI d c) = PubKeyI (derivePubKey d) c
+
+-- | Tweak a public key.
+tweakPubKey :: PubKey -> Hash256 -> Maybe PubKey
+tweakPubKey p h = tweakAddPubKey p =<< tweak (encode h)
+
+-- | Elliptic curve private key type with expected public key compression
+-- information. Compression information is stored in private key WIF formats and
+-- needs to be preserved to generate the correct address from the corresponding
+-- public key.
+data SecKeyI = SecKeyI
+    { secKeyData       :: !SecKey
+    , secKeyCompressed :: !Bool
+    } deriving (Eq, Show, Read)
+
+instance NFData SecKeyI where
+    rnf (SecKeyI k c) = k `seq` rnf c `seq` ()
+
+-- | Wrap private key with corresponding public key compression flag.
+wrapSecKey :: Bool -> SecKey -> SecKeyI
+wrapSecKey c d = SecKeyI d c
+
+secKeyGet :: Get SecKey
+secKeyGet = do
+    bs <- getByteString 32
+    maybe (fail "invalid private key") return (secKey bs)
+
+secKeyPut :: Putter SecKey
+secKeyPut = putByteString . getSecKey
+
+
+-- | Decode Casascius mini private keys (22 or 30 characters).
+fromMiniKey :: ByteString -> Maybe SecKeyI
+fromMiniKey bs = do
+    guard checkShortKey
+    wrapSecKey False <$> secKey (encode (sha256 bs))
+  where
+    checkHash = encode $ sha256 $ bs `BS.append` "?"
+    checkShortKey = BS.length bs `elem` [22, 30] && BS.head checkHash == 0x00
+
+-- | Tweak a private key.
+tweakSecKey :: SecKey -> Hash256 -> Maybe SecKey
+tweakSecKey key h = tweakAddSecKey key =<< tweak (encode h)
diff --git a/src/Network/Haskoin/Keys/Extended.hs b/src/Network/Haskoin/Keys/Extended.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Keys/Extended.hs
@@ -0,0 +1,857 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs             #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Keys.Extended
+    (
+      -- * Extended Keys
+      -- | See BIP32 for details:
+      -- <https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki>
+      XPubKey(..)
+    , XPrvKey(..)
+    , ChainCode
+    , KeyIndex
+    , DerivationException(..)
+    , makeXPrvKey
+    , deriveXPubKey
+    , prvSubKey
+    , pubSubKey
+    , hardSubKey
+    , xPrvIsHard
+    , xPubIsHard
+    , xPrvChild
+    , xPubChild
+    , xPubID
+    , xPrvID
+    , xPubFP
+    , xPrvFP
+    , xPubAddr
+    , xPubExport
+    , xPrvExport
+    , xPubImport
+    , xPrvImport
+    , xPrvWif
+    , putXPrvKey
+    , putXPubKey
+    , getXPrvKey
+    , getXPubKey
+    , xPubFromJSON
+    , xPrvFromJSON
+
+      -- ** Helpers
+    , prvSubKeys
+    , pubSubKeys
+    , hardSubKeys
+    , deriveAddr
+    , deriveAddrs
+    , deriveMSAddr
+    , deriveMSAddrs
+    , cycleIndex
+
+      -- ** Derivation Paths
+    , DerivPathI(..)
+    , AnyDeriv, HardDeriv, SoftDeriv
+    , HardOrAny
+    , AnyOrSoft
+    , DerivPath
+    , HardPath
+    , SoftPath
+    , Bip32PathIndex (..)
+    , derivePath
+    , derivePubPath
+    , toHard
+    , toSoft
+    , toGeneric
+    , (++/)
+    , pathToStr
+    , listToPath
+    , pathToList
+
+      -- ** Derivation Path Parser
+    , XKey(..)
+    , ParsedPath(..)
+    , parsePath
+    , parseHard
+    , parseSoft
+    , applyPath
+    , derivePathAddr
+    , derivePathAddrs
+    , derivePathMSAddr
+    , derivePathMSAddrs
+    , concatBip32Segments
+    ) where
+
+import           Control.Applicative
+import           Control.DeepSeq                (NFData, rnf)
+import           Control.Exception              (Exception, throw)
+import           Control.Monad                  (guard, mzero, unless, (<=<))
+import           Data.Aeson                     as A (FromJSON, ToJSON,
+                                                      Value (String), parseJSON,
+                                                      toJSON, withText)
+import           Data.Aeson.Types               (Parser)
+import           Data.Bits                      (clearBit, setBit, testBit)
+import           Data.ByteString                (ByteString)
+import qualified Data.ByteString                as BS
+import           Data.Either                    (fromRight)
+import           Data.List                      (foldl')
+import           Data.List.Split                (splitOn)
+import           Data.Maybe                     (fromMaybe)
+import           Data.Monoid                    ((<>))
+import           Data.Serialize                 as S (Serialize, decode, encode,
+                                                      get, put)
+import           Data.Serialize.Get             (Get, getWord32be, getWord8,
+                                                 runGet)
+import           Data.Serialize.Put             (Putter, putWord32be, putWord8,
+                                                 runPut)
+import           Data.String                    (IsString, fromString)
+import           Data.String.Conversions        (cs)
+import           Data.Typeable                  (Typeable)
+import           Data.Word                      (Word32, Word8)
+import           Network.Haskoin.Address
+import           Network.Haskoin.Address.Base58
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Keys.Common
+import           Network.Haskoin.Script
+import           Network.Haskoin.Util
+import           Text.Read                      as R
+import           Text.Read.Lex
+
+
+-- | A derivation exception is thrown in the very unlikely event that a
+-- derivation is invalid.
+newtype DerivationException = DerivationException String
+    deriving (Eq, Read, Show, Typeable)
+
+instance Exception DerivationException
+
+type ChainCode = Hash256
+type KeyIndex = Word32
+
+-- | Data type representing an extended BIP32 private key. An extended key
+-- is a node in a tree of key derivations. It has a depth in the tree, a
+-- parent node and an index to differentiate it from other siblings.
+data XPrvKey = XPrvKey
+    { xPrvDepth  :: !Word8     -- ^ depth in the tree
+    , xPrvParent :: !Word32    -- ^ fingerprint of parent
+    , xPrvIndex  :: !KeyIndex  -- ^ derivation index
+    , xPrvChain  :: !ChainCode -- ^ chain code
+    , xPrvKey    :: !SecKey    -- ^ private key of this node
+    , xPrvNet    :: !Network
+    } deriving (Eq)
+
+instance Ord XPrvKey where
+    compare k1 k2 = xPrvExport k1 `compare` xPrvExport k2
+
+instance Show XPrvKey where
+    showsPrec _ = shows . xPrvExport
+
+instance Read XPrvKey where
+    readPrec = do
+        R.String str <- lexP
+        let bs = cs str
+            f k n = k <|> xPrvImport n bs
+        maybe pfail return $ foldl' f Nothing allNets
+
+instance NFData XPrvKey where
+    rnf (XPrvKey d p i c k n) =
+        rnf d `seq`
+        rnf p `seq` rnf i `seq` rnf c `seq` k `seq` rnf n `seq` ()
+
+instance ToJSON XPrvKey where
+    toJSON = A.String . xPrvExport
+
+-- | Data type representing an extended BIP32 public key.
+data XPubKey = XPubKey
+    { xPubDepth  :: !Word8     -- ^ depth in the tree
+    , xPubParent :: !Word32    -- ^ fingerprint of parent
+    , xPubIndex  :: !KeyIndex  -- ^ derivation index
+    , xPubChain  :: !ChainCode -- ^ chain code
+    , xPubKey    :: !PubKey    -- ^ public key of this node
+    , xPubNet    :: !Network
+    } deriving (Eq)
+
+instance Ord XPubKey where
+    compare k1 k2 = xPubExport k1 `compare` xPubExport k2
+
+instance Show XPubKey where
+    showsPrec _ = shows . xPubExport
+
+instance Read XPubKey where
+    readPrec = do
+        R.String str <- lexP
+        let bs = cs str
+            f k n = k <|> xPubImport n bs
+        maybe pfail return $ foldl' f Nothing allNets
+
+instance NFData XPubKey where
+    rnf (XPubKey d p i c k n) =
+        rnf d `seq`
+        rnf p `seq` rnf i `seq` rnf c `seq` k `seq` rnf n `seq` ()
+
+instance ToJSON XPubKey where
+    toJSON = A.String . xPubExport
+
+-- | Decode an extended public key from a JSON string
+xPubFromJSON :: Network -> Value -> Parser XPubKey
+xPubFromJSON net =
+    withText "xpub" $ \t ->
+        case xPubImport net t of
+            Nothing -> fail "could not read xpub"
+            Just x  -> return x
+
+-- | Decode an extended private key from a JSON string
+xPrvFromJSON :: Network -> Value -> Parser XPrvKey
+xPrvFromJSON net =
+    withText "xprv" $ \t ->
+        case xPrvImport net t of
+            Nothing -> fail "could not read xprv"
+            Just x  -> return x
+
+-- | Build a BIP32 compatible extended private key from a bytestring. This will
+-- produce a root node (@depth=0@ and @parent=0@).
+makeXPrvKey :: Network -> ByteString -> XPrvKey
+makeXPrvKey net bs =
+    XPrvKey 0 0 0 c k net
+  where
+    (p, c) = split512 $ hmac512 "Bitcoin seed" bs
+    k     = fromMaybe err (secKey (encode p))
+    err   = throw $ DerivationException "Invalid seed"
+
+-- | Derive an extended public key from an extended private key. This function
+-- will preserve the depth, parent, index and chaincode fields of the extended
+-- private keys.
+deriveXPubKey :: XPrvKey -> XPubKey
+deriveXPubKey (XPrvKey d p i c k n) = XPubKey d p i c (derivePubKey k) n
+
+-- | Compute a private, soft child key derivation. A private soft derivation
+-- will allow the equivalent extended public key to derive the public key for
+-- this child. Given a parent key /m/ and a derivation index /i/, this function
+-- will compute /m\/i/.
+--
+-- Soft derivations allow for more flexibility such as read-only wallets.
+-- However, care must be taken not the leak both the parent extended public key
+-- and one of the extended child private keys as this would compromise the
+-- extended parent private key.
+prvSubKey :: XPrvKey  -- ^ extended parent private key
+          -> KeyIndex -- ^ child derivation index
+          -> XPrvKey  -- ^ extended child private key
+prvSubKey xkey child
+    | child >= 0 && child < 0x80000000 =
+        XPrvKey (xPrvDepth xkey + 1) (xPrvFP xkey) child c k (xPrvNet xkey)
+    | otherwise = error "Invalid child derivation index"
+  where
+    pK = xPubKey $ deriveXPubKey xkey
+    msg = BS.append (exportPubKey True pK) (encode child)
+    (a, c) = split512 $ hmac512 (encode $ xPrvChain xkey) msg
+    k = fromMaybe err $ tweakSecKey (xPrvKey xkey) a
+    err = throw $ DerivationException "Invalid prvSubKey derivation"
+
+-- | Compute a public, soft child key derivation. Given a parent key /M/
+-- and a derivation index /i/, this function will compute /M\/i/.
+pubSubKey :: XPubKey  -- ^ extended parent public key
+          -> KeyIndex -- ^ child derivation index
+          -> XPubKey  -- ^ extended child public key
+pubSubKey xKey child
+    | child >= 0 && child < 0x80000000 =
+        XPubKey (xPubDepth xKey + 1) (xPubFP xKey) child c pK (xPubNet xKey)
+    | otherwise = error "Invalid child derivation index"
+  where
+    msg    = BS.append (exportPubKey True (xPubKey xKey)) (encode child)
+    (a, c) = split512 $ hmac512 (encode $ xPubChain xKey) msg
+    pK     = fromMaybe err $ tweakPubKey (xPubKey xKey) a
+    err    = throw $ DerivationException "Invalid pubSubKey derivation"
+
+-- | Compute a hard child key derivation. Hard derivations can only be computed
+-- for private keys. Hard derivations do not allow the parent public key to
+-- derive the child public keys. However, they are safer as a breach of the
+-- parent public key and child private keys does not lead to a breach of the
+-- parent private key. Given a parent key /m/ and a derivation index /i/, this
+-- function will compute /m\/i'/.
+hardSubKey :: XPrvKey  -- ^ extended parent private key
+           -> KeyIndex -- ^ child derivation index
+           -> XPrvKey  -- ^ extended child private key
+hardSubKey xkey child
+    | child >= 0 && child < 0x80000000 =
+        XPrvKey (xPrvDepth xkey + 1) (xPrvFP xkey) i c k (xPrvNet xkey)
+    | otherwise = error "Invalid child derivation index"
+  where
+    i      = setBit child 31
+    msg    = BS.append (bsPadPrvKey $ xPrvKey xkey) (encode i)
+    (a, c) = split512 $ hmac512 (encode $ xPrvChain xkey) msg
+    k      = fromMaybe err $ tweakSecKey (xPrvKey xkey) a
+    err    = throw $ DerivationException "Invalid hardSubKey derivation"
+
+-- | Returns true if the extended private key was derived through a hard
+-- derivation.
+xPrvIsHard :: XPrvKey -> Bool
+xPrvIsHard k = testBit (xPrvIndex k) 31
+
+-- | Returns true if the extended public key was derived through a hard
+-- derivation.
+xPubIsHard :: XPubKey -> Bool
+xPubIsHard k = testBit (xPubIndex k) 31
+
+-- | Returns the derivation index of this extended private key without the hard
+-- bit set.
+xPrvChild :: XPrvKey -> KeyIndex
+xPrvChild k = clearBit (xPrvIndex k) 31
+
+-- | Returns the derivation index of this extended public key without the hard
+-- bit set.
+xPubChild :: XPubKey -> KeyIndex
+xPubChild k = clearBit (xPubIndex k) 31
+
+-- | Computes the key identifier of an extended private key.
+xPrvID :: XPrvKey -> Hash160
+xPrvID = xPubID . deriveXPubKey
+
+-- | Computes the key identifier of an extended public key.
+xPubID :: XPubKey -> Hash160
+xPubID = ripemd160 . encode . sha256 . exportPubKey True . xPubKey
+
+-- | Computes the key fingerprint of an extended private key.
+xPrvFP :: XPrvKey -> Word32
+xPrvFP =
+    fromRight err . decode . BS.take 4 . encode . xPrvID
+  where
+    err = error "Could not decode xPrvFP"
+
+-- | Computes the key fingerprint of an extended public key.
+xPubFP :: XPubKey -> Word32
+xPubFP =
+    fromRight err . decode . BS.take 4 . encode . xPubID
+  where
+    err = error "Could not decode xPubFP"
+
+-- | Computer the 'Address' of an extended public key.
+xPubAddr :: XPubKey -> Address
+xPubAddr xkey = pubKeyAddr (xPubNet xkey) (wrapPubKey True (xPubKey xkey))
+
+-- | Exports an extended private key to the BIP32 key export format ('Base58').
+xPrvExport :: XPrvKey -> Base58
+xPrvExport = encodeBase58Check . runPut . putXPrvKey
+
+-- | Exports an extended public key to the BIP32 key export format ('Base58').
+xPubExport :: XPubKey -> Base58
+xPubExport = encodeBase58Check . runPut . putXPubKey
+
+-- | Decodes a BIP32 encoded extended private key. This function will fail if
+-- invalid base 58 characters are detected or if the checksum fails.
+xPrvImport :: Network -> Base58 -> Maybe XPrvKey
+xPrvImport net = eitherToMaybe . runGet (getXPrvKey net) <=< decodeBase58Check
+
+-- | Decodes a BIP32 encoded extended public key. This function will fail if
+-- invalid base 58 characters are detected or if the checksum fails.
+xPubImport :: Network -> Base58 -> Maybe XPubKey
+xPubImport net = eitherToMaybe . runGet (getXPubKey net) <=< decodeBase58Check
+
+-- | Export an extended private key to WIF (Wallet Import Format).
+xPrvWif :: XPrvKey -> Base58
+xPrvWif xkey = toWif (xPrvNet xkey) (wrapSecKey True (xPrvKey xkey))
+
+-- | Parse a binary extended private key.
+getXPrvKey :: Network -> Get XPrvKey
+getXPrvKey net = do
+        ver <- getWord32be
+        unless (ver == getExtSecretPrefix net) $ fail
+            "Get: Invalid version for extended private key"
+        XPrvKey <$> getWord8
+                <*> getWord32be
+                <*> getWord32be
+                <*> S.get
+                <*> getPadPrvKey
+                <*> pure net
+
+-- | Serialize an extended private key.
+putXPrvKey :: Putter XPrvKey
+putXPrvKey k = do
+        putWord32be  $ getExtSecretPrefix (xPrvNet k)
+        putWord8     $ xPrvDepth k
+        putWord32be  $ xPrvParent k
+        putWord32be  $ xPrvIndex k
+        put          $ xPrvChain k
+        putPadPrvKey $ xPrvKey k
+
+-- | Parse a binary extended public key.
+getXPubKey :: Network -> Get XPubKey
+getXPubKey net = do
+        ver <- getWord32be
+        unless (ver == getExtPubKeyPrefix net) $ fail
+            "Get: Invalid version for extended public key"
+        XPubKey <$> getWord8
+                <*> getWord32be
+                <*> getWord32be
+                <*> S.get
+                <*> (pubKeyPoint <$> S.get)
+                <*> pure net
+
+-- | Serialize an extended public key.
+putXPubKey :: Putter XPubKey
+putXPubKey k = do
+        putWord32be $ getExtPubKeyPrefix (xPubNet k)
+        putWord8    $ xPubDepth k
+        putWord32be $ xPubParent k
+        putWord32be $ xPubIndex k
+        put         $ xPubChain k
+        put         $ wrapPubKey True (xPubKey k)
+
+{- Derivation helpers -}
+
+-- | Cyclic list of all private soft child key derivations of a parent key
+-- starting from an offset index.
+prvSubKeys :: XPrvKey -> KeyIndex -> [(XPrvKey, KeyIndex)]
+prvSubKeys k = map (\i -> (prvSubKey k i, i)) . cycleIndex
+
+-- | Cyclic list of all public soft child key derivations of a parent key
+-- starting from an offset index.
+pubSubKeys :: XPubKey -> KeyIndex -> [(XPubKey, KeyIndex)]
+pubSubKeys k = map (\i -> (pubSubKey k i, i)) . cycleIndex
+
+-- | Cyclic list of all hard child key derivations of a parent key starting
+-- from an offset index.
+hardSubKeys :: XPrvKey -> KeyIndex -> [(XPrvKey, KeyIndex)]
+hardSubKeys k = map (\i -> (hardSubKey k i, i)) . cycleIndex
+
+-- | Derive an address from a public key and an index. The derivation type
+-- is a public, soft derivation.
+deriveAddr :: XPubKey -> KeyIndex -> (Address, PubKey)
+deriveAddr k i =
+    (xPubAddr key, xPubKey key)
+  where
+    key = pubSubKey k i
+
+-- | Cyclic list of all addresses derived from a public key starting from an
+-- offset index. The derivation types are public, soft derivations.
+deriveAddrs :: XPubKey -> KeyIndex -> [(Address, PubKey, KeyIndex)]
+deriveAddrs k =
+    map f . cycleIndex
+  where
+    f i = let (a, key) = deriveAddr k i in (a, key, i)
+
+-- | Derive a multisig address from a list of public keys, the number of
+-- required signatures /m/ and a derivation index. The derivation type is a
+-- public, soft derivation.
+deriveMSAddr :: Network -> [XPubKey] -> Int -> KeyIndex -> (Address, RedeemScript)
+deriveMSAddr net keys m i
+    | all ((== net) . xPubNet) keys = (p2shAddr net rdm, rdm)
+    | otherwise = error "Some extended public keys on the wrong network"
+  where
+    rdm = sortMulSig $ PayMulSig k m
+    k = map (wrapPubKey True . xPubKey . flip pubSubKey i) keys
+
+-- | Cyclic list of all multisig addresses derived from a list of public keys,
+-- a number of required signatures /m/ and starting from an offset index. The
+-- derivation type is a public, soft derivation.
+deriveMSAddrs :: Network -> [XPubKey] -> Int -> KeyIndex
+              -> [(Address, RedeemScript, KeyIndex)]
+deriveMSAddrs net keys m = map f . cycleIndex
+  where
+    f i =
+        let (a, rdm) = deriveMSAddr net keys m i
+         in (a, rdm, i)
+
+-- | Helper function to go through derivation indices.
+cycleIndex :: KeyIndex -> [KeyIndex]
+cycleIndex i
+    | i == 0         = cycle [0..0x7fffffff]
+    | i < 0x80000000 = cycle $ [i..0x7fffffff] ++ [0..(i-1)]
+    | otherwise      = error $ "cycleIndex: invalid index " ++ show i
+
+{- Derivation Paths -}
+
+data HardDeriv
+data AnyDeriv
+data SoftDeriv
+
+type HardPath = DerivPathI HardDeriv
+type DerivPath = DerivPathI AnyDeriv
+type SoftPath = DerivPathI SoftDeriv
+
+class HardOrAny a
+instance HardOrAny HardDeriv
+instance HardOrAny AnyDeriv
+
+class AnyOrSoft a
+instance AnyOrSoft AnyDeriv
+instance AnyOrSoft SoftDeriv
+
+-- | Data type representing a derivation path. Two constructors are provided
+-- for specifying soft or hard derivations. The path /\/0\/1'\/2/ for example can be
+-- expressed as @'Deriv' :\/ 0 :| 1 :\/ 2@. The 'HardOrAny' and 'AnyOrSoft' type
+-- classes are used to constrain the valid values for the phantom type /t/. If
+-- you mix hard '(:|)' and soft '(:\/)' paths, the only valid type for /t/ is 'AnyDeriv'.
+-- Otherwise, /t/ can be 'HardDeriv' if you only have hard derivation or 'SoftDeriv'
+-- if you only have soft derivations.
+--
+-- Using this type is as easy as writing the required derivation like in these
+-- example:
+--
+-- > Deriv :/ 0 :/ 1 :/ 2 :: SoftPath
+-- > Deriv :| 0 :| 1 :| 2 :: HardPath
+-- > Deriv :| 0 :/ 1 :/ 2 :: DerivPath
+data DerivPathI t where
+    (:|)  :: HardOrAny t => !(DerivPathI t) -> !KeyIndex -> DerivPathI t
+    (:/)  :: AnyOrSoft t => !(DerivPathI t) -> !KeyIndex -> DerivPathI t
+    Deriv :: DerivPathI t
+
+instance NFData (DerivPathI t) where
+    rnf p = case p of
+        next :| i -> rnf i `seq` rnf next
+        next :/ i -> rnf i `seq` rnf next
+        Deriv     -> ()
+
+instance Eq (DerivPathI t) where
+    (nextA :| iA) == (nextB :| iB) = iA == iB && nextA == nextB
+    (nextA :/ iA) == (nextB :/ iB) = iA == iB && nextA == nextB
+    Deriv         == Deriv         = True
+    _             == _             = False
+
+instance Serialize DerivPath where
+    get = listToPath <$> S.get
+    put = put . pathToList
+
+-- | Get a list of derivation indices from a derivation path.
+pathToList :: DerivPathI t -> [KeyIndex]
+pathToList =
+    reverse . go
+  where
+    go (next :| i) = setBit i 31 : go next
+    go (next :/ i) = i : go next
+    go _           = []
+
+-- | Convert a list of derivation indices to a derivation path.
+listToPath :: [KeyIndex] -> DerivPath
+listToPath =
+    go . reverse
+  where
+    go (i:is)
+        | testBit i 31 = go is :| clearBit i 31
+        | otherwise    = go is :/ i
+    go [] = Deriv
+
+-- | Convert a derivation path to a human-readable string.
+pathToStr :: DerivPathI t -> String
+pathToStr p =
+    case p of
+        next :| i -> concat [ pathToStr next, "/", show i, "'" ]
+        next :/ i -> concat [ pathToStr next, "/", show i ]
+        Deriv     -> ""
+
+-- | Turn a derivation path into a hard derivation path. Will fail if the path
+-- contains soft derivations.
+toHard :: DerivPathI t -> Maybe HardPath
+toHard p = case p of
+    next :| i -> (:| i) <$> toHard next
+    Deriv     -> Just Deriv
+    _         -> Nothing
+
+-- | Turn a derivatino path into a soft derivation path. Will fail if the path
+-- has hard derivations.
+toSoft :: DerivPathI t -> Maybe SoftPath
+toSoft p = case p of
+    next :/ i -> (:/ i) <$> toSoft next
+    Deriv     -> Just Deriv
+    _         -> Nothing
+
+-- | Make a derivation path generic.
+toGeneric :: DerivPathI t -> DerivPath
+toGeneric p = case p of
+    next :/ i -> toGeneric next :/ i
+    next :| i -> toGeneric next :| i
+    Deriv     -> Deriv
+
+-- | Append two derivation paths together. The result will be a mixed
+-- derivation path.
+(++/) :: DerivPathI t1 -> DerivPathI t2 -> DerivPath
+(++/) p1 p2 =
+    go id (toGeneric p2) $ toGeneric p1
+  where
+    go f p = case p of
+        next :/ i -> go (f . (:/ i)) $ toGeneric next
+        next :| i -> go (f . (:| i)) $ toGeneric next
+        _         -> f
+
+-- | Derive a private key from a derivation path
+derivePath :: DerivPathI t -> XPrvKey -> XPrvKey
+derivePath = go id
+  where
+    -- Build the full derivation function starting from the end
+    go f p = case p of
+        next :| i -> go (f . flip hardSubKey i) next
+        next :/ i -> go (f . flip prvSubKey i) next
+        _         -> f
+
+-- | Derive a public key from a soft derivation path
+derivePubPath :: SoftPath -> XPubKey -> XPubKey
+derivePubPath = go id
+  where
+    -- Build the full derivation function starting from the end
+    go f p = case p of
+        next :/ i -> go (f . flip pubSubKey i) next
+        _         -> f
+
+instance Show DerivPath where
+    showsPrec d p = showParen (d > 10) $
+        showString "DerivPath " . shows (pathToStr p)
+
+instance Read DerivPath where
+    readPrec = parens $ do
+        R.Ident "DerivPath" <- lexP
+        R.String str <- lexP
+        maybe pfail return $ getParsedPath <$> parsePath str
+
+instance Show HardPath where
+    showsPrec d p = showParen (d > 10) $
+        showString "HardPath " . shows (pathToStr p)
+
+instance Read HardPath where
+    readPrec = parens $ do
+        R.Ident "HardPath" <- lexP
+        R.String str <- lexP
+        maybe pfail return $ parseHard str
+
+instance Show SoftPath where
+    showsPrec d p = showParen (d > 10) $
+        showString "SoftPath " . shows (pathToStr p)
+
+instance Read SoftPath where
+    readPrec = parens $ do
+        R.Ident "SoftPath" <- lexP
+        R.String str <- lexP
+        maybe pfail return $ parseSoft str
+
+instance IsString ParsedPath where
+    fromString =
+        fromMaybe e . parsePath
+      where
+        e = error "Could not parse derivation path"
+
+instance IsString DerivPath where
+    fromString =
+        getParsedPath . fromMaybe e . parsePath
+      where
+        e = error "Could not parse derivation path"
+
+instance IsString HardPath where
+    fromString =
+        fromMaybe e . parseHard
+      where
+        e = error "Could not parse hard derivation path"
+
+instance IsString SoftPath where
+    fromString =
+        fromMaybe e . parseSoft
+      where
+        e = error "Could not parse soft derivation path"
+
+instance FromJSON ParsedPath where
+    parseJSON = withText "ParsedPath" $ \str -> case parsePath $ cs str of
+        Just p -> return p
+        _      -> mzero
+
+instance FromJSON DerivPath where
+    parseJSON = withText "DerivPath" $ \str -> case parsePath $ cs str of
+        Just p -> return $ getParsedPath p
+        _      -> mzero
+
+instance FromJSON HardPath where
+    parseJSON = withText "HardPath" $ \str -> case parseHard $ cs str of
+        Just p -> return p
+        _      -> mzero
+
+instance FromJSON SoftPath where
+    parseJSON = withText "SoftPath" $ \str -> case parseSoft $ cs str of
+        Just p -> return p
+        _      -> mzero
+
+instance ToJSON (DerivPathI t) where
+    toJSON = A.String . cs . pathToStr
+
+instance ToJSON ParsedPath where
+    toJSON (ParsedPrv p)   = A.String . cs . ("m" ++) . pathToStr $ p
+    toJSON (ParsedPub p)   = A.String . cs . ("M" ++) . pathToStr $ p
+    toJSON (ParsedEmpty p) = A.String . cs . ("" ++) . pathToStr $ p
+
+{- Parsing derivation paths of the form m/1/2'/3 or M/1/2'/3 -}
+
+-- | Type for parsing derivation paths of the form /m\/1\/2'\/3/ or
+-- /M\/1\/2'\/3/.
+data ParsedPath = ParsedPrv   { getParsedPath :: !DerivPath }
+                | ParsedPub   { getParsedPath :: !DerivPath }
+                | ParsedEmpty { getParsedPath :: !DerivPath }
+  deriving Eq
+
+instance Show ParsedPath where
+    showsPrec d p = showParen (d > 10) $ showString "ParsedPath " . shows f
+      where
+        f =
+            case p of
+                ParsedPrv d'   -> "m" <> pathToStr d'
+                ParsedPub d'   -> "M" <> pathToStr d'
+                ParsedEmpty d' -> pathToStr d'
+
+instance Read ParsedPath where
+    readPrec = parens $ do
+        R.Ident "ParsedPath" <- lexP
+        R.String str <- lexP
+        maybe pfail return $ parsePath str
+
+-- | Parse derivation path string for extended key.
+-- Forms: /m\/0'\/2/, /M\/2\/3\/4/.
+parsePath :: String -> Maybe ParsedPath
+parsePath str = do
+    res <- concatBip32Segments <$> mapM parseBip32PathIndex xs
+    case x of
+        "m" -> Just $ ParsedPrv res
+        "M" -> Just $ ParsedPub res
+        ""  -> Just $ ParsedEmpty res
+        _   -> Nothing
+  where
+    (x : xs) = splitOn "/" str
+
+-- | Concatenate derivation path indices into a derivation path.
+concatBip32Segments :: [Bip32PathIndex] -> DerivPath
+concatBip32Segments = foldl' appendBip32Segment Deriv
+
+-- | Append an extra derivation path index element into an existing path.
+appendBip32Segment :: DerivPath -> Bip32PathIndex  -> DerivPath
+appendBip32Segment d (Bip32SoftIndex i) = d :/ i
+appendBip32Segment d (Bip32HardIndex i) = d :| i
+
+-- | Parse a BIP32 derivation path index element from a string.
+parseBip32PathIndex :: String -> Maybe Bip32PathIndex
+parseBip32PathIndex segment = case reads segment of
+    [(i, "" )] -> guard (is31Bit i) >> return (Bip32SoftIndex i)
+    [(i, "'")] -> guard (is31Bit i) >> return (Bip32HardIndex i)
+    _          -> Nothing
+
+-- | Type for BIP32 path index element.
+data Bip32PathIndex = Bip32HardIndex KeyIndex
+                    | Bip32SoftIndex KeyIndex
+  deriving Eq
+
+instance Show Bip32PathIndex where
+    showsPrec d (Bip32HardIndex i) = showParen (d > 10) $
+        showString "Bip32HardIndex " . shows i
+    showsPrec d (Bip32SoftIndex i) = showParen (d > 10) $
+        showString "Bip32SoftIndex " . shows i
+
+instance Read Bip32PathIndex where
+    readPrec = h <|> s
+      where
+        h =
+            parens $ do
+                R.Ident "Bip32HardIndex" <- lexP
+                R.Number n <- lexP
+                maybe pfail return $
+                    Bip32HardIndex . fromIntegral <$> numberToInteger n
+        s =
+            parens $ do
+                R.Ident "Bip32SoftIndex" <- lexP
+                R.Number n <- lexP
+                maybe pfail return $
+                    Bip32SoftIndex . fromIntegral <$> numberToInteger n
+
+-- | Test whether the number could be a valid BIP32 derivation index.
+is31Bit :: (Integral a) => a -> Bool
+is31Bit i = i >= 0 && i < 0x80000000
+
+-- | Helper function to parse a hard path.
+parseHard :: String -> Maybe HardPath
+parseHard = toHard . getParsedPath <=< parsePath
+
+-- | Helper function to parse a soft path.
+parseSoft :: String -> Maybe SoftPath
+parseSoft = toSoft . getParsedPath <=< parsePath
+
+-- | Data type representing a private or public key with its respective network.
+data XKey
+    = XPrv { getXKeyPrv :: !XPrvKey
+           , getXKeyNet :: !Network }
+    | XPub { getXKeyPub :: !XPubKey
+           , getXKeyNet :: !Network }
+    deriving (Eq, Show)
+
+-- | Apply a parsed path to an extended key to derive the new key defined in the
+-- path. If the path starts with /m/, a private key will be returned and if the
+-- path starts with /M/, a public key will be returned. Private derivations on a
+-- public key, and public derivations with a hard segment, return an error
+-- value.
+applyPath :: ParsedPath -> XKey -> Either String XKey
+applyPath path key =
+    case (path, key) of
+        (ParsedPrv _, XPrv k n) -> return $ XPrv (derivPrvF k) n
+        (ParsedPrv _, XPub {}) -> Left "applyPath: Invalid public key"
+        (ParsedPub _, XPrv k n) -> return $ XPub (deriveXPubKey (derivPrvF k)) n
+        (ParsedPub _, XPub k n) -> derivPubFE >>= \f -> return $ XPub (f k) n
+    -- For empty parsed paths, we take a hint from the provided key
+        (ParsedEmpty _, XPrv k n) -> return $ XPrv (derivPrvF k) n
+        (ParsedEmpty _, XPub k n) -> derivPubFE >>= \f -> return $ XPub (f k) n
+  where
+    derivPrvF = goPrv id $ getParsedPath path
+    derivPubFE = goPubE id $ getParsedPath path
+    -- Build the full private derivation function starting from the end
+    goPrv f p =
+        case p of
+            next :| i -> goPrv (f . flip hardSubKey i) next
+            next :/ i -> goPrv (f . flip prvSubKey i) next
+            Deriv     -> f
+    -- Build the full public derivation function starting from the end
+    goPubE f p =
+        case p of
+            next :/ i -> goPubE (f . flip pubSubKey i) next
+            Deriv     -> Right f
+            _         -> Left "applyPath: Invalid hard derivation"
+
+{- Helpers for derivation paths and addresses -}
+
+-- | Derive an address from a given parent path.
+derivePathAddr :: XPubKey -> SoftPath -> KeyIndex -> (Address, PubKey)
+derivePathAddr key path = deriveAddr (derivePubPath path key)
+
+-- | Cyclic list of all addresses derived from a given parent path and starting
+-- from the given offset index.
+derivePathAddrs ::
+       XPubKey -> SoftPath -> KeyIndex -> [(Address, PubKey, KeyIndex)]
+derivePathAddrs key path = deriveAddrs (derivePubPath path key)
+
+-- | Derive a multisig address from a given parent path. The number of required
+-- signatures (m in m of n) is also needed.
+derivePathMSAddr ::
+       Network
+    -> [XPubKey]
+    -> SoftPath
+    -> Int
+    -> KeyIndex
+    -> (Address, RedeemScript)
+derivePathMSAddr net keys path =
+    deriveMSAddr net $ map (derivePubPath path) keys
+
+-- | Cyclic list of all multisig addresses derived from a given parent path and
+-- starting from the given offset index. The number of required signatures
+-- (m in m of n) is also needed.
+derivePathMSAddrs ::
+       Network
+    -> [XPubKey]
+    -> SoftPath
+    -> Int
+    -> KeyIndex
+    -> [(Address, RedeemScript, KeyIndex)]
+derivePathMSAddrs net keys path =
+    deriveMSAddrs net $ map (derivePubPath path) keys
+
+{- Utilities for extended keys -}
+
+-- | De-serialize HDW-specific private key.
+getPadPrvKey :: Get SecKey
+getPadPrvKey = do
+    pad <- getWord8
+    unless (pad == 0x00) $ fail "Private key must be padded with 0x00"
+    secKeyGet
+
+-- | Serialize HDW-specific private key.
+putPadPrvKey :: Putter SecKey
+putPadPrvKey p = putWord8 0x00 >> secKeyPut p
+
+bsPadPrvKey :: SecKey -> ByteString
+bsPadPrvKey = runPut . putPadPrvKey
diff --git a/src/Network/Haskoin/Keys/Mnemonic.hs b/src/Network/Haskoin/Keys/Mnemonic.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Keys/Mnemonic.hs
@@ -0,0 +1,508 @@
+{-# LANGUAGE OverloadedStrings #-}
+-- | Mnemonic keys (BIP-39). Only English dictionary.
+module Network.Haskoin.Keys.Mnemonic
+    ( -- * Mnemonic Sentences
+      Entropy
+    , Mnemonic
+    , Passphrase
+    , Seed
+    , toMnemonic
+    , fromMnemonic
+    , mnemonicToSeed
+    ) where
+
+import           Control.Monad           (when)
+import           Crypto.Hash             (SHA256 (..), hashWith)
+import           Crypto.KDF.PBKDF2       (Parameters (..), fastPBKDF2_SHA512)
+import           Data.Bits               (shiftL, shiftR)
+import qualified Data.ByteArray          as BA
+import           Data.ByteString         (ByteString)
+import qualified Data.ByteString         as BS
+import qualified Data.ByteString.Char8   as C (unwords, words)
+import           Data.List
+import qualified Data.Map.Strict         as M
+import           Data.Maybe
+import           Data.String.Conversions (cs)
+import           Data.Text               (Text)
+import qualified Data.Text               as T
+import qualified Data.Text.Encoding      as E
+import           Data.Vector             (Vector, (!))
+import qualified Data.Vector             as V
+import           Network.Haskoin.Util
+
+-- | Random data used to create a mnemonic sentence. Use a good entropy source.
+-- You will get your coins stolen if you don't. You have been warned.
+type Entropy = ByteString
+
+-- | Human-readable mnemonic sentence.
+type Mnemonic = Text
+
+-- | Optional passphrase for mnemnoic sentence.
+type Passphrase = ByteString
+
+-- | Seed for a private key from a mnemonic sentence.
+type Seed = ByteString
+
+-- | Mnemonic key checksum.
+type Checksum = ByteString
+
+-- | Paremeters for PBKDF2 function.
+pbkdfParams :: Parameters
+pbkdfParams = Parameters {iterCounts = 2048, outputLength = 64}
+
+-- | Provide intial 'Entropy' as a 'ByteString' of length multiple of 4 bytes.
+-- Output a 'Mnemonic' sentence.
+toMnemonic :: Entropy -> Either String Mnemonic
+toMnemonic ent = do
+    when (BS.null ent) $
+        Left "toMnemonic: entropy can not be empty"
+    when (remainder /= 0) $
+        Left "toMnemonic: entropy must be multiples of 4 bytes"
+    when (cs_len > 16) $
+        Left "toMnemonic: maximum entropy is 64 bytes (512 bits)"
+    return ms
+  where
+    (cs_len, remainder) = BS.length ent `quotRem` 4
+    c = calcCS cs_len ent
+    indices = bsToIndices $ ent `BS.append` c
+    ms = T.unwords $ map (wl!) indices
+
+-- | Revert 'toMnemonic'. Do not use this to generate a 'Seed'. Instead use
+-- 'mnemonicToSeed'. This outputs the original 'Entropy' used to generate a
+-- 'Mnemonic' sentence.
+fromMnemonic :: Mnemonic -> Either String Entropy
+fromMnemonic ms = do
+    when (T.null ms) $
+        Left "fromMnemonic: empty mnemonic"
+    when (word_count > 48) $
+        Left $ "fromMnemonic: too many words: " ++ show word_count
+    when (word_count `mod` 3 /= 0) $
+        Left $ "fromMnemonic: wrong number of words:" ++ show word_count
+    ms_bs <- indicesToBS =<< getIndices ms_words
+    let (ms_ent, ms_cs) = BS.splitAt (ent_len * 4) ms_bs
+        ms_cs_num = numCS cs_len ms_cs
+        ent_cs_num = numCS cs_len $ calcCS cs_len ms_ent
+    when (ent_cs_num /= ms_cs_num) $
+        Left $ "fromMnemonic: checksum failed: " ++ sh ent_cs_num ms_cs_num
+    return ms_ent
+  where
+    ms_words = T.words ms
+    word_count = length ms_words
+    (ent_len, cs_len) = (word_count * 11) `quotRem` 32
+    sh cs_a cs_b = show cs_a ++ " /= " ++ show cs_b
+
+-- | Compute 'Checksum'.
+calcCS :: Int -> Entropy -> Checksum
+calcCS len = getBits len . BA.convert . hashWith SHA256
+
+numCS :: Int -> Entropy -> Integer
+numCS len =
+    shiftCS . bsToInteger
+  where
+    shiftCS = case 8 - len `mod` 8 of
+        8 -> id
+        x -> flip shiftR x
+
+-- | Turn an arbitrary sequence of characters into a 512-bit 'Seed'. Use
+-- 'mnemonicToSeed' to get a seed from a 'Mnemonic' sentence. Warning: Does not
+-- perform NFKD normalization.
+anyToSeed :: Passphrase -> Mnemonic -> Seed
+anyToSeed pf ms =
+    fastPBKDF2_SHA512 pbkdfParams (E.encodeUtf8 ms) ("mnemonic" `mappend` pf)
+
+-- | Get a 512-bit 'Seed' from a 'Mnemonic' sentence. Will validate checksum.
+-- 'Passphrase' can be used to protect the 'Mnemonic'. Use an empty string as
+-- 'Passphrase' if none is required.
+mnemonicToSeed :: Passphrase -> Mnemonic -> Either String Seed
+mnemonicToSeed pf ms = do
+    ent <- fromMnemonic ms
+    mnm <- toMnemonic ent
+    return $ anyToSeed pf mnm
+
+-- | Get indices of words in word list.
+getIndices :: [Text] -> Either String [Int]
+getIndices ws
+    | null n = return $ catMaybes i
+    | otherwise = Left $ "getIndices: words not found: " ++ cs w
+  where
+    i = map (`M.lookup` wl') ws
+    n = elemIndices Nothing i
+    w = T.unwords $ map (ws !!) n
+
+-- | Turn a list of 11-bit numbers into a 'ByteString'
+indicesToBS :: [Int] -> Either String ByteString
+indicesToBS is = do
+    when lrg $ Left "indicesToBS: index larger or equal than 2048"
+    return . pad . integerToBS $ foldl' f 0 is `shiftL` shift_width
+  where
+    lrg = isJust $ find (>= 2048) is
+    (q, r) = (length is * 11) `quotRem` 8
+    shift_width =
+        if r == 0
+            then 0
+            else 8 - r
+    bl =
+        if r == 0
+            then q
+            else q + 1 -- length of resulting ByteString
+    pad bs = BS.append (BS.replicate (bl - BS.length bs) 0x00) bs
+    f acc x = (acc `shiftL` 11) + fromIntegral x
+
+-- | Turn a 'ByteString' into a list of 11-bit numbers.
+bsToIndices :: ByteString -> [Int]
+bsToIndices bs =
+    reverse . go q $ bsToInteger bs `shiftR` r
+  where
+    (q, r) = (BS.length bs * 8) `quotRem` 11
+    go 0 _ = []
+    go n i = fromIntegral (i `mod` 2048) : go (n - 1) (i `shiftR` 11)
+
+wl' :: M.Map Text Int
+wl' = V.ifoldr' (\i w m -> M.insert w i m) M.empty wl
+
+-- | Standard English dictionary from BIP-39 specification.
+wl :: Vector Text
+wl = V.fromListN 2048
+    [ "abandon", "ability", "able", "about", "above", "absent"
+    , "absorb", "abstract", "absurd", "abuse", "access", "accident"
+    , "account", "accuse", "achieve", "acid", "acoustic", "acquire"
+    , "across", "act", "action", "actor", "actress", "actual"
+    , "adapt", "add", "addict", "address", "adjust", "admit"
+    , "adult", "advance", "advice", "aerobic", "affair", "afford"
+    , "afraid", "again", "age", "agent", "agree", "ahead"
+    , "aim", "air", "airport", "aisle", "alarm", "album"
+    , "alcohol", "alert", "alien", "all", "alley", "allow"
+    , "almost", "alone", "alpha", "already", "also", "alter"
+    , "always", "amateur", "amazing", "among", "amount", "amused"
+    , "analyst", "anchor", "ancient", "anger", "angle", "angry"
+    , "animal", "ankle", "announce", "annual", "another", "answer"
+    , "antenna", "antique", "anxiety", "any", "apart", "apology"
+    , "appear", "apple", "approve", "april", "arch", "arctic"
+    , "area", "arena", "argue", "arm", "armed", "armor"
+    , "army", "around", "arrange", "arrest", "arrive", "arrow"
+    , "art", "artefact", "artist", "artwork", "ask", "aspect"
+    , "assault", "asset", "assist", "assume", "asthma", "athlete"
+    , "atom", "attack", "attend", "attitude", "attract", "auction"
+    , "audit", "august", "aunt", "author", "auto", "autumn"
+    , "average", "avocado", "avoid", "awake", "aware", "away"
+    , "awesome", "awful", "awkward", "axis", "baby", "bachelor"
+    , "bacon", "badge", "bag", "balance", "balcony", "ball"
+    , "bamboo", "banana", "banner", "bar", "barely", "bargain"
+    , "barrel", "base", "basic", "basket", "battle", "beach"
+    , "bean", "beauty", "because", "become", "beef", "before"
+    , "begin", "behave", "behind", "believe", "below", "belt"
+    , "bench", "benefit", "best", "betray", "better", "between"
+    , "beyond", "bicycle", "bid", "bike", "bind", "biology"
+    , "bird", "birth", "bitter", "black", "blade", "blame"
+    , "blanket", "blast", "bleak", "bless", "blind", "blood"
+    , "blossom", "blouse", "blue", "blur", "blush", "board"
+    , "boat", "body", "boil", "bomb", "bone", "bonus"
+    , "book", "boost", "border", "boring", "borrow", "boss"
+    , "bottom", "bounce", "box", "boy", "bracket", "brain"
+    , "brand", "brass", "brave", "bread", "breeze", "brick"
+    , "bridge", "brief", "bright", "bring", "brisk", "broccoli"
+    , "broken", "bronze", "broom", "brother", "brown", "brush"
+    , "bubble", "buddy", "budget", "buffalo", "build", "bulb"
+    , "bulk", "bullet", "bundle", "bunker", "burden", "burger"
+    , "burst", "bus", "business", "busy", "butter", "buyer"
+    , "buzz", "cabbage", "cabin", "cable", "cactus", "cage"
+    , "cake", "call", "calm", "camera", "camp", "can"
+    , "canal", "cancel", "candy", "cannon", "canoe", "canvas"
+    , "canyon", "capable", "capital", "captain", "car", "carbon"
+    , "card", "cargo", "carpet", "carry", "cart", "case"
+    , "cash", "casino", "castle", "casual", "cat", "catalog"
+    , "catch", "category", "cattle", "caught", "cause", "caution"
+    , "cave", "ceiling", "celery", "cement", "census", "century"
+    , "cereal", "certain", "chair", "chalk", "champion", "change"
+    , "chaos", "chapter", "charge", "chase", "chat", "cheap"
+    , "check", "cheese", "chef", "cherry", "chest", "chicken"
+    , "chief", "child", "chimney", "choice", "choose", "chronic"
+    , "chuckle", "chunk", "churn", "cigar", "cinnamon", "circle"
+    , "citizen", "city", "civil", "claim", "clap", "clarify"
+    , "claw", "clay", "clean", "clerk", "clever", "click"
+    , "client", "cliff", "climb", "clinic", "clip", "clock"
+    , "clog", "close", "cloth", "cloud", "clown", "club"
+    , "clump", "cluster", "clutch", "coach", "coast", "coconut"
+    , "code", "coffee", "coil", "coin", "collect", "color"
+    , "column", "combine", "come", "comfort", "comic", "common"
+    , "company", "concert", "conduct", "confirm", "congress", "connect"
+    , "consider", "control", "convince", "cook", "cool", "copper"
+    , "copy", "coral", "core", "corn", "correct", "cost"
+    , "cotton", "couch", "country", "couple", "course", "cousin"
+    , "cover", "coyote", "crack", "cradle", "craft", "cram"
+    , "crane", "crash", "crater", "crawl", "crazy", "cream"
+    , "credit", "creek", "crew", "cricket", "crime", "crisp"
+    , "critic", "crop", "cross", "crouch", "crowd", "crucial"
+    , "cruel", "cruise", "crumble", "crunch", "crush", "cry"
+    , "crystal", "cube", "culture", "cup", "cupboard", "curious"
+    , "current", "curtain", "curve", "cushion", "custom", "cute"
+    , "cycle", "dad", "damage", "damp", "dance", "danger"
+    , "daring", "dash", "daughter", "dawn", "day", "deal"
+    , "debate", "debris", "decade", "december", "decide", "decline"
+    , "decorate", "decrease", "deer", "defense", "define", "defy"
+    , "degree", "delay", "deliver", "demand", "demise", "denial"
+    , "dentist", "deny", "depart", "depend", "deposit", "depth"
+    , "deputy", "derive", "describe", "desert", "design", "desk"
+    , "despair", "destroy", "detail", "detect", "develop", "device"
+    , "devote", "diagram", "dial", "diamond", "diary", "dice"
+    , "diesel", "diet", "differ", "digital", "dignity", "dilemma"
+    , "dinner", "dinosaur", "direct", "dirt", "disagree", "discover"
+    , "disease", "dish", "dismiss", "disorder", "display", "distance"
+    , "divert", "divide", "divorce", "dizzy", "doctor", "document"
+    , "dog", "doll", "dolphin", "domain", "donate", "donkey"
+    , "donor", "door", "dose", "double", "dove", "draft"
+    , "dragon", "drama", "drastic", "draw", "dream", "dress"
+    , "drift", "drill", "drink", "drip", "drive", "drop"
+    , "drum", "dry", "duck", "dumb", "dune", "during"
+    , "dust", "dutch", "duty", "dwarf", "dynamic", "eager"
+    , "eagle", "early", "earn", "earth", "easily", "east"
+    , "easy", "echo", "ecology", "economy", "edge", "edit"
+    , "educate", "effort", "egg", "eight", "either", "elbow"
+    , "elder", "electric", "elegant", "element", "elephant", "elevator"
+    , "elite", "else", "embark", "embody", "embrace", "emerge"
+    , "emotion", "employ", "empower", "empty", "enable", "enact"
+    , "end", "endless", "endorse", "enemy", "energy", "enforce"
+    , "engage", "engine", "enhance", "enjoy", "enlist", "enough"
+    , "enrich", "enroll", "ensure", "enter", "entire", "entry"
+    , "envelope", "episode", "equal", "equip", "era", "erase"
+    , "erode", "erosion", "error", "erupt", "escape", "essay"
+    , "essence", "estate", "eternal", "ethics", "evidence", "evil"
+    , "evoke", "evolve", "exact", "example", "excess", "exchange"
+    , "excite", "exclude", "excuse", "execute", "exercise", "exhaust"
+    , "exhibit", "exile", "exist", "exit", "exotic", "expand"
+    , "expect", "expire", "explain", "expose", "express", "extend"
+    , "extra", "eye", "eyebrow", "fabric", "face", "faculty"
+    , "fade", "faint", "faith", "fall", "false", "fame"
+    , "family", "famous", "fan", "fancy", "fantasy", "farm"
+    , "fashion", "fat", "fatal", "father", "fatigue", "fault"
+    , "favorite", "feature", "february", "federal", "fee", "feed"
+    , "feel", "female", "fence", "festival", "fetch", "fever"
+    , "few", "fiber", "fiction", "field", "figure", "file"
+    , "film", "filter", "final", "find", "fine", "finger"
+    , "finish", "fire", "firm", "first", "fiscal", "fish"
+    , "fit", "fitness", "fix", "flag", "flame", "flash"
+    , "flat", "flavor", "flee", "flight", "flip", "float"
+    , "flock", "floor", "flower", "fluid", "flush", "fly"
+    , "foam", "focus", "fog", "foil", "fold", "follow"
+    , "food", "foot", "force", "forest", "forget", "fork"
+    , "fortune", "forum", "forward", "fossil", "foster", "found"
+    , "fox", "fragile", "frame", "frequent", "fresh", "friend"
+    , "fringe", "frog", "front", "frost", "frown", "frozen"
+    , "fruit", "fuel", "fun", "funny", "furnace", "fury"
+    , "future", "gadget", "gain", "galaxy", "gallery", "game"
+    , "gap", "garage", "garbage", "garden", "garlic", "garment"
+    , "gas", "gasp", "gate", "gather", "gauge", "gaze"
+    , "general", "genius", "genre", "gentle", "genuine", "gesture"
+    , "ghost", "giant", "gift", "giggle", "ginger", "giraffe"
+    , "girl", "give", "glad", "glance", "glare", "glass"
+    , "glide", "glimpse", "globe", "gloom", "glory", "glove"
+    , "glow", "glue", "goat", "goddess", "gold", "good"
+    , "goose", "gorilla", "gospel", "gossip", "govern", "gown"
+    , "grab", "grace", "grain", "grant", "grape", "grass"
+    , "gravity", "great", "green", "grid", "grief", "grit"
+    , "grocery", "group", "grow", "grunt", "guard", "guess"
+    , "guide", "guilt", "guitar", "gun", "gym", "habit"
+    , "hair", "half", "hammer", "hamster", "hand", "happy"
+    , "harbor", "hard", "harsh", "harvest", "hat", "have"
+    , "hawk", "hazard", "head", "health", "heart", "heavy"
+    , "hedgehog", "height", "hello", "helmet", "help", "hen"
+    , "hero", "hidden", "high", "hill", "hint", "hip"
+    , "hire", "history", "hobby", "hockey", "hold", "hole"
+    , "holiday", "hollow", "home", "honey", "hood", "hope"
+    , "horn", "horror", "horse", "hospital", "host", "hotel"
+    , "hour", "hover", "hub", "huge", "human", "humble"
+    , "humor", "hundred", "hungry", "hunt", "hurdle", "hurry"
+    , "hurt", "husband", "hybrid", "ice", "icon", "idea"
+    , "identify", "idle", "ignore", "ill", "illegal", "illness"
+    , "image", "imitate", "immense", "immune", "impact", "impose"
+    , "improve", "impulse", "inch", "include", "income", "increase"
+    , "index", "indicate", "indoor", "industry", "infant", "inflict"
+    , "inform", "inhale", "inherit", "initial", "inject", "injury"
+    , "inmate", "inner", "innocent", "input", "inquiry", "insane"
+    , "insect", "inside", "inspire", "install", "intact", "interest"
+    , "into", "invest", "invite", "involve", "iron", "island"
+    , "isolate", "issue", "item", "ivory", "jacket", "jaguar"
+    , "jar", "jazz", "jealous", "jeans", "jelly", "jewel"
+    , "job", "join", "joke", "journey", "joy", "judge"
+    , "juice", "jump", "jungle", "junior", "junk", "just"
+    , "kangaroo", "keen", "keep", "ketchup", "key", "kick"
+    , "kid", "kidney", "kind", "kingdom", "kiss", "kit"
+    , "kitchen", "kite", "kitten", "kiwi", "knee", "knife"
+    , "knock", "know", "lab", "label", "labor", "ladder"
+    , "lady", "lake", "lamp", "language", "laptop", "large"
+    , "later", "latin", "laugh", "laundry", "lava", "law"
+    , "lawn", "lawsuit", "layer", "lazy", "leader", "leaf"
+    , "learn", "leave", "lecture", "left", "leg", "legal"
+    , "legend", "leisure", "lemon", "lend", "length", "lens"
+    , "leopard", "lesson", "letter", "level", "liar", "liberty"
+    , "library", "license", "life", "lift", "light", "like"
+    , "limb", "limit", "link", "lion", "liquid", "list"
+    , "little", "live", "lizard", "load", "loan", "lobster"
+    , "local", "lock", "logic", "lonely", "long", "loop"
+    , "lottery", "loud", "lounge", "love", "loyal", "lucky"
+    , "luggage", "lumber", "lunar", "lunch", "luxury", "lyrics"
+    , "machine", "mad", "magic", "magnet", "maid", "mail"
+    , "main", "major", "make", "mammal", "man", "manage"
+    , "mandate", "mango", "mansion", "manual", "maple", "marble"
+    , "march", "margin", "marine", "market", "marriage", "mask"
+    , "mass", "master", "match", "material", "math", "matrix"
+    , "matter", "maximum", "maze", "meadow", "mean", "measure"
+    , "meat", "mechanic", "medal", "media", "melody", "melt"
+    , "member", "memory", "mention", "menu", "mercy", "merge"
+    , "merit", "merry", "mesh", "message", "metal", "method"
+    , "middle", "midnight", "milk", "million", "mimic", "mind"
+    , "minimum", "minor", "minute", "miracle", "mirror", "misery"
+    , "miss", "mistake", "mix", "mixed", "mixture", "mobile"
+    , "model", "modify", "mom", "moment", "monitor", "monkey"
+    , "monster", "month", "moon", "moral", "more", "morning"
+    , "mosquito", "mother", "motion", "motor", "mountain", "mouse"
+    , "move", "movie", "much", "muffin", "mule", "multiply"
+    , "muscle", "museum", "mushroom", "music", "must", "mutual"
+    , "myself", "mystery", "myth", "naive", "name", "napkin"
+    , "narrow", "nasty", "nation", "nature", "near", "neck"
+    , "need", "negative", "neglect", "neither", "nephew", "nerve"
+    , "nest", "net", "network", "neutral", "never", "news"
+    , "next", "nice", "night", "noble", "noise", "nominee"
+    , "noodle", "normal", "north", "nose", "notable", "note"
+    , "nothing", "notice", "novel", "now", "nuclear", "number"
+    , "nurse", "nut", "oak", "obey", "object", "oblige"
+    , "obscure", "observe", "obtain", "obvious", "occur", "ocean"
+    , "october", "odor", "off", "offer", "office", "often"
+    , "oil", "okay", "old", "olive", "olympic", "omit"
+    , "once", "one", "onion", "online", "only", "open"
+    , "opera", "opinion", "oppose", "option", "orange", "orbit"
+    , "orchard", "order", "ordinary", "organ", "orient", "original"
+    , "orphan", "ostrich", "other", "outdoor", "outer", "output"
+    , "outside", "oval", "oven", "over", "own", "owner"
+    , "oxygen", "oyster", "ozone", "pact", "paddle", "page"
+    , "pair", "palace", "palm", "panda", "panel", "panic"
+    , "panther", "paper", "parade", "parent", "park", "parrot"
+    , "party", "pass", "patch", "path", "patient", "patrol"
+    , "pattern", "pause", "pave", "payment", "peace", "peanut"
+    , "pear", "peasant", "pelican", "pen", "penalty", "pencil"
+    , "people", "pepper", "perfect", "permit", "person", "pet"
+    , "phone", "photo", "phrase", "physical", "piano", "picnic"
+    , "picture", "piece", "pig", "pigeon", "pill", "pilot"
+    , "pink", "pioneer", "pipe", "pistol", "pitch", "pizza"
+    , "place", "planet", "plastic", "plate", "play", "please"
+    , "pledge", "pluck", "plug", "plunge", "poem", "poet"
+    , "point", "polar", "pole", "police", "pond", "pony"
+    , "pool", "popular", "portion", "position", "possible", "post"
+    , "potato", "pottery", "poverty", "powder", "power", "practice"
+    , "praise", "predict", "prefer", "prepare", "present", "pretty"
+    , "prevent", "price", "pride", "primary", "print", "priority"
+    , "prison", "private", "prize", "problem", "process", "produce"
+    , "profit", "program", "project", "promote", "proof", "property"
+    , "prosper", "protect", "proud", "provide", "public", "pudding"
+    , "pull", "pulp", "pulse", "pumpkin", "punch", "pupil"
+    , "puppy", "purchase", "purity", "purpose", "purse", "push"
+    , "put", "puzzle", "pyramid", "quality", "quantum", "quarter"
+    , "question", "quick", "quit", "quiz", "quote", "rabbit"
+    , "raccoon", "race", "rack", "radar", "radio", "rail"
+    , "rain", "raise", "rally", "ramp", "ranch", "random"
+    , "range", "rapid", "rare", "rate", "rather", "raven"
+    , "raw", "razor", "ready", "real", "reason", "rebel"
+    , "rebuild", "recall", "receive", "recipe", "record", "recycle"
+    , "reduce", "reflect", "reform", "refuse", "region", "regret"
+    , "regular", "reject", "relax", "release", "relief", "rely"
+    , "remain", "remember", "remind", "remove", "render", "renew"
+    , "rent", "reopen", "repair", "repeat", "replace", "report"
+    , "require", "rescue", "resemble", "resist", "resource", "response"
+    , "result", "retire", "retreat", "return", "reunion", "reveal"
+    , "review", "reward", "rhythm", "rib", "ribbon", "rice"
+    , "rich", "ride", "ridge", "rifle", "right", "rigid"
+    , "ring", "riot", "ripple", "risk", "ritual", "rival"
+    , "river", "road", "roast", "robot", "robust", "rocket"
+    , "romance", "roof", "rookie", "room", "rose", "rotate"
+    , "rough", "round", "route", "royal", "rubber", "rude"
+    , "rug", "rule", "run", "runway", "rural", "sad"
+    , "saddle", "sadness", "safe", "sail", "salad", "salmon"
+    , "salon", "salt", "salute", "same", "sample", "sand"
+    , "satisfy", "satoshi", "sauce", "sausage", "save", "say"
+    , "scale", "scan", "scare", "scatter", "scene", "scheme"
+    , "school", "science", "scissors", "scorpion", "scout", "scrap"
+    , "screen", "script", "scrub", "sea", "search", "season"
+    , "seat", "second", "secret", "section", "security", "seed"
+    , "seek", "segment", "select", "sell", "seminar", "senior"
+    , "sense", "sentence", "series", "service", "session", "settle"
+    , "setup", "seven", "shadow", "shaft", "shallow", "share"
+    , "shed", "shell", "sheriff", "shield", "shift", "shine"
+    , "ship", "shiver", "shock", "shoe", "shoot", "shop"
+    , "short", "shoulder", "shove", "shrimp", "shrug", "shuffle"
+    , "shy", "sibling", "sick", "side", "siege", "sight"
+    , "sign", "silent", "silk", "silly", "silver", "similar"
+    , "simple", "since", "sing", "siren", "sister", "situate"
+    , "six", "size", "skate", "sketch", "ski", "skill"
+    , "skin", "skirt", "skull", "slab", "slam", "sleep"
+    , "slender", "slice", "slide", "slight", "slim", "slogan"
+    , "slot", "slow", "slush", "small", "smart", "smile"
+    , "smoke", "smooth", "snack", "snake", "snap", "sniff"
+    , "snow", "soap", "soccer", "social", "sock", "soda"
+    , "soft", "solar", "soldier", "solid", "solution", "solve"
+    , "someone", "song", "soon", "sorry", "sort", "soul"
+    , "sound", "soup", "source", "south", "space", "spare"
+    , "spatial", "spawn", "speak", "special", "speed", "spell"
+    , "spend", "sphere", "spice", "spider", "spike", "spin"
+    , "spirit", "split", "spoil", "sponsor", "spoon", "sport"
+    , "spot", "spray", "spread", "spring", "spy", "square"
+    , "squeeze", "squirrel", "stable", "stadium", "staff", "stage"
+    , "stairs", "stamp", "stand", "start", "state", "stay"
+    , "steak", "steel", "stem", "step", "stereo", "stick"
+    , "still", "sting", "stock", "stomach", "stone", "stool"
+    , "story", "stove", "strategy", "street", "strike", "strong"
+    , "struggle", "student", "stuff", "stumble", "style", "subject"
+    , "submit", "subway", "success", "such", "sudden", "suffer"
+    , "sugar", "suggest", "suit", "summer", "sun", "sunny"
+    , "sunset", "super", "supply", "supreme", "sure", "surface"
+    , "surge", "surprise", "surround", "survey", "suspect", "sustain"
+    , "swallow", "swamp", "swap", "swarm", "swear", "sweet"
+    , "swift", "swim", "swing", "switch", "sword", "symbol"
+    , "symptom", "syrup", "system", "table", "tackle", "tag"
+    , "tail", "talent", "talk", "tank", "tape", "target"
+    , "task", "taste", "tattoo", "taxi", "teach", "team"
+    , "tell", "ten", "tenant", "tennis", "tent", "term"
+    , "test", "text", "thank", "that", "theme", "then"
+    , "theory", "there", "they", "thing", "this", "thought"
+    , "three", "thrive", "throw", "thumb", "thunder", "ticket"
+    , "tide", "tiger", "tilt", "timber", "time", "tiny"
+    , "tip", "tired", "tissue", "title", "toast", "tobacco"
+    , "today", "toddler", "toe", "together", "toilet", "token"
+    , "tomato", "tomorrow", "tone", "tongue", "tonight", "tool"
+    , "tooth", "top", "topic", "topple", "torch", "tornado"
+    , "tortoise", "toss", "total", "tourist", "toward", "tower"
+    , "town", "toy", "track", "trade", "traffic", "tragic"
+    , "train", "transfer", "trap", "trash", "travel", "tray"
+    , "treat", "tree", "trend", "trial", "tribe", "trick"
+    , "trigger", "trim", "trip", "trophy", "trouble", "truck"
+    , "true", "truly", "trumpet", "trust", "truth", "try"
+    , "tube", "tuition", "tumble", "tuna", "tunnel", "turkey"
+    , "turn", "turtle", "twelve", "twenty", "twice", "twin"
+    , "twist", "two", "type", "typical", "ugly", "umbrella"
+    , "unable", "unaware", "uncle", "uncover", "under", "undo"
+    , "unfair", "unfold", "unhappy", "uniform", "unique", "unit"
+    , "universe", "unknown", "unlock", "until", "unusual", "unveil"
+    , "update", "upgrade", "uphold", "upon", "upper", "upset"
+    , "urban", "urge", "usage", "use", "used", "useful"
+    , "useless", "usual", "utility", "vacant", "vacuum", "vague"
+    , "valid", "valley", "valve", "van", "vanish", "vapor"
+    , "various", "vast", "vault", "vehicle", "velvet", "vendor"
+    , "venture", "venue", "verb", "verify", "version", "very"
+    , "vessel", "veteran", "viable", "vibrant", "vicious", "victory"
+    , "video", "view", "village", "vintage", "violin", "virtual"
+    , "virus", "visa", "visit", "visual", "vital", "vivid"
+    , "vocal", "voice", "void", "volcano", "volume", "vote"
+    , "voyage", "wage", "wagon", "wait", "walk", "wall"
+    , "walnut", "want", "warfare", "warm", "warrior", "wash"
+    , "wasp", "waste", "water", "wave", "way", "wealth"
+    , "weapon", "wear", "weasel", "weather", "web", "wedding"
+    , "weekend", "weird", "welcome", "west", "wet", "whale"
+    , "what", "wheat", "wheel", "when", "where", "whip"
+    , "whisper", "wide", "width", "wife", "wild", "will"
+    , "win", "window", "wine", "wing", "wink", "winner"
+    , "winter", "wire", "wisdom", "wise", "wish", "witness"
+    , "wolf", "woman", "wonder", "wood", "wool", "word"
+    , "work", "world", "worry", "worth", "wrap", "wreck"
+    , "wrestle", "wrist", "write", "wrong", "yard", "year"
+    , "yellow", "you", "young", "youth", "zebra", "zero"
+    , "zone", "zoo"
+    ]
diff --git a/src/Network/Haskoin/Network.hs b/src/Network/Haskoin/Network.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Network.hs
@@ -0,0 +1,15 @@
+{-|
+  This package provides basic types used for the Bitcoin networking protocol
+  together with Data.Serialize instances for efficiently serializing and
+  de-serializing them. More information on the bitcoin protocol is available
+  here: <http://en.bitcoin.it/wiki/Protocol_specification>
+-}
+module Network.Haskoin.Network
+    ( module Common
+    , module Message
+    , module Bloom
+    ) where
+
+import           Network.Haskoin.Network.Bloom   as Bloom
+import           Network.Haskoin.Network.Common  as Common
+import           Network.Haskoin.Network.Message as Message
diff --git a/src/Network/Haskoin/Network/Bloom.hs b/src/Network/Haskoin/Network/Bloom.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Network/Bloom.hs
@@ -0,0 +1,222 @@
+{-|
+  Bloom filters are used to reduce data transfer when synchronizing thin cients.
+  When bloom filters are used a client will obtain filtered blocks that only
+  contain transactions that pass the bloom filter. Transactions announced via
+  inv messages also pass the filter.
+-}
+module Network.Haskoin.Network.Bloom
+    ( -- * Bloom Filters
+      BloomFlags(..)
+    , BloomFilter(..)
+    , FilterLoad(..)
+    , FilterAdd(..)
+    , bloomCreate
+    , bloomInsert
+    , bloomContains
+    , isBloomValid
+    , isBloomEmpty
+    , isBloomFull
+    , acceptsFilters
+    ) where
+
+import           Control.DeepSeq                (NFData, rnf)
+import           Control.Monad                  (forM_, replicateM)
+import           Data.Bits
+import           Data.ByteString                (ByteString)
+import qualified Data.ByteString                as BS
+import qualified Data.Foldable                  as F
+import           Data.Hash.Murmur               (murmur3)
+import qualified Data.Sequence                  as S
+import           Data.Serialize                 (Serialize, get, put)
+import           Data.Serialize.Get             (getByteString, getWord32le,
+                                                 getWord8)
+import           Data.Serialize.Put             (putByteString, putWord32le,
+                                                 putWord8)
+import           Data.Word
+import           Network.Haskoin.Network.Common
+
+-- | 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001%
+maxBloomSize :: Int
+maxBloomSize = 36000
+
+maxHashFuncs :: Word32
+maxHashFuncs = 50
+
+ln2Squared :: Double
+ln2Squared = 0.4804530139182014246671025263266649717305529515945455
+
+ln2 :: Double
+ln2 = 0.6931471805599453094172321214581765680755001343602552
+
+bitMask :: [Word8]
+bitMask = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80]
+
+-- | The bloom flags are used to tell the remote peer how to auto-update
+-- the provided bloom filter.
+data BloomFlags
+    = BloomUpdateNone -- ^ never update
+    | BloomUpdateAll -- ^ auto-update on all outputs
+    | BloomUpdateP2PubKeyOnly
+    -- ^ auto-update on pay-to-pubkey or pay-to-multisig (default)
+    deriving (Eq, Show, Read)
+
+instance NFData BloomFlags where rnf x = seq x ()
+
+instance Serialize BloomFlags where
+    get = go =<< getWord8
+      where
+        go 0 = return BloomUpdateNone
+        go 1 = return BloomUpdateAll
+        go 2 = return BloomUpdateP2PubKeyOnly
+        go _ = fail "BloomFlags get: Invalid bloom flag"
+
+    put f = putWord8 $ case f of
+        BloomUpdateNone         -> 0
+        BloomUpdateAll          -> 1
+        BloomUpdateP2PubKeyOnly -> 2
+
+-- | A bloom filter is a probabilistic data structure that SPV clients send to
+-- other peers to filter the set of transactions received from them. Bloom
+-- filters can have false positives but not false negatives. Some transactions
+-- that pass the filter may not be relevant to the receiving peer. By
+-- controlling the false positive rate, SPV nodes can trade off bandwidth
+-- versus privacy.
+data BloomFilter = BloomFilter
+    { bloomData      :: !(S.Seq Word8)
+    -- ^ bloom filter data
+    , bloomHashFuncs :: !Word32
+    -- ^ number of hash functions for this filter
+    , bloomTweak     :: !Word32
+    -- ^ hash function random nonce
+    , bloomFlags     :: !BloomFlags
+    -- ^ bloom filter auto-update flags
+    }
+    deriving (Eq, Show, Read)
+
+instance NFData BloomFilter where
+    rnf (BloomFilter d h t g) =
+        rnf d `seq` rnf h `seq` rnf t `seq` rnf g
+
+instance Serialize BloomFilter where
+
+    get = BloomFilter <$> (S.fromList <$> (readDat =<< get))
+                      <*> getWord32le <*> getWord32le
+                      <*> get
+      where
+        readDat (VarInt len) = replicateM (fromIntegral len) getWord8
+
+    put (BloomFilter dat hashFuncs tweak flags) = do
+        put $ VarInt $ fromIntegral $ S.length dat
+        forM_ (F.toList dat) putWord8
+        putWord32le hashFuncs
+        putWord32le tweak
+        put flags
+
+-- | Set a new bloom filter on the peer connection.
+newtype FilterLoad = FilterLoad { filterLoadBloomFilter :: BloomFilter }
+    deriving (Eq, Show, Read)
+
+instance NFData FilterLoad where
+    rnf (FilterLoad f) = rnf f
+
+instance Serialize FilterLoad where
+    get = FilterLoad <$> get
+    put (FilterLoad f) = put f
+
+-- | Add the given data element to the connections current filter without
+-- requiring a completely new one to be set.
+newtype FilterAdd = FilterAdd { getFilterData :: ByteString }
+    deriving (Eq, Show, Read)
+
+instance NFData FilterAdd where
+    rnf (FilterAdd f) = rnf f
+
+instance Serialize FilterAdd where
+    get = do
+        (VarInt len) <- get
+        dat <- getByteString $ fromIntegral len
+        return $ FilterAdd dat
+
+    put (FilterAdd bs) = do
+        put $ VarInt $ fromIntegral $ BS.length bs
+        putByteString bs
+
+
+-- | Build a bloom filter that will provide the given false positive rate when
+-- the given number of elements have been inserted.
+bloomCreate :: Int          -- ^ number of elements
+            -> Double       -- ^ false positive rate
+            -> Word32       -- ^ random nonce (tweak) for the hash function
+            -> BloomFlags   -- ^ bloom filter flags
+            -> BloomFilter  -- ^ bloom filter
+bloomCreate numElem fpRate =
+    BloomFilter (S.replicate bloomSize 0) numHashF
+  where
+    -- Bloom filter size in bytes
+    bloomSize = truncate $ min a b / 8
+    -- Suggested size in bits
+    a         = -1 / ln2Squared * fromIntegral numElem * log fpRate
+    -- Maximum size in bits
+    b         = fromIntegral $ maxBloomSize * 8
+    numHashF  = truncate $ min c (fromIntegral maxHashFuncs)
+    -- Suggested number of hash functions
+    c         = fromIntegral bloomSize * 8 / fromIntegral numElem * ln2
+
+bloomHash :: BloomFilter -> Word32 -> ByteString -> Word32
+bloomHash bfilter hashNum bs =
+    murmur3 seed bs `mod` (fromIntegral (S.length (bloomData bfilter)) * 8)
+  where
+    seed = hashNum * 0xfba4c795 + bloomTweak bfilter
+
+-- | Insert arbitrary data into a bloom filter. Returns the new bloom filter
+-- containing the new data.
+bloomInsert :: BloomFilter    -- ^ Original bloom filter
+            -> ByteString     -- ^ New data to insert
+            -> BloomFilter    -- ^ Bloom filter containing the new data
+bloomInsert bfilter bs
+    | isBloomFull bfilter = bfilter
+    | otherwise = bfilter { bloomData = newData }
+  where
+    idxs    = map (\i -> bloomHash bfilter i bs) [0..bloomHashFuncs bfilter - 1]
+    upd s i = S.adjust (.|. bitMask !! fromIntegral (7 .&. i))
+                       (fromIntegral $ i `shiftR` 3) s
+    newData = foldl upd (bloomData bfilter) idxs
+
+-- | Tests if some arbitrary data matches the filter. This can be either because
+-- the data was inserted into the filter or because it is a false positive.
+bloomContains :: BloomFilter    -- ^ Bloom filter
+              -> ByteString
+              -- ^ Data that will be checked against the given bloom filter
+              -> Bool
+              -- ^ Returns True if the data matches the filter
+bloomContains bfilter bs
+    | isBloomFull bfilter  = True
+    | isBloomEmpty bfilter = False
+    | otherwise            = all isSet idxs
+  where
+    s       = bloomData bfilter
+    idxs    = map (\i -> bloomHash bfilter i bs) [0..bloomHashFuncs bfilter - 1]
+    isSet i = S.index s (fromIntegral $ i `shiftR` 3)
+          .&. (bitMask !! fromIntegral (7 .&. i)) /= 0
+
+-- TODO: Write bloomRelevantUpdate
+-- bloomRelevantUpdate :: BloomFilter -> Tx -> Hash256 -> Maybe BloomFilter
+
+-- | Returns True if the filter is empty (all bytes set to 0x00)
+isBloomEmpty :: BloomFilter -> Bool
+isBloomEmpty bfilter = all (== 0x00) $ F.toList $ bloomData bfilter
+
+-- | Returns True if the filter is full (all bytes set to 0xff)
+isBloomFull :: BloomFilter -> Bool
+isBloomFull bfilter = all (== 0xff) $ F.toList $ bloomData bfilter
+
+-- | Tests if a given bloom filter is valid.
+isBloomValid :: BloomFilter -- ^ Bloom filter to test
+             -> Bool        -- ^ True if the given filter is valid
+isBloomValid bfilter =
+    S.length (bloomData bfilter) <= maxBloomSize &&
+    bloomHashFuncs bfilter <= maxHashFuncs
+
+-- | Does the peer with these version services accept bloom filters?
+acceptsFilters :: Word64 -> Bool
+acceptsFilters srv = srv .&. (1 `shiftL` 2) /= 0
diff --git a/src/Network/Haskoin/Network/Common.hs b/src/Network/Haskoin/Network/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Network/Common.hs
@@ -0,0 +1,629 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
+module Network.Haskoin.Network.Common
+    ( -- * Network Data Types
+      Addr(..)
+    , NetworkAddressTime
+    , Alert(..)
+    , GetData(..)
+    , Inv(..)
+    , InvVector(..)
+    , InvType(..)
+    , NetworkAddress(..)
+    , NotFound(..)
+    , Ping(..)
+    , Pong(..)
+    , Reject(..)
+    , RejectCode(..)
+    , VarInt(..)
+    , VarString(..)
+    , Version(..)
+    , MessageCommand(..)
+      -- ** Useful Functions
+    , reject
+    , nodeNone
+    , nodeNetwork
+    , nodeGetUTXO
+    , nodeBloom
+    , nodeWitness
+    , nodeXThin
+    , commandToString
+    , stringToCommand
+    ) where
+
+import           Control.DeepSeq             (NFData, rnf)
+import           Control.Monad               (forM_, liftM2, replicateM, unless)
+import           Data.Bits                   (shiftL)
+import           Data.ByteString             (ByteString)
+import qualified Data.ByteString             as B
+import           Data.ByteString.Char8       as C (replicate)
+import           Data.Maybe
+import           Data.Monoid                 ((<>))
+import           Data.Serialize              as S
+import           Data.String
+import           Data.String.Conversions     (cs)
+import           Data.Word                   (Word32, Word64)
+import           Network.Haskoin.Crypto.Hash
+import           Network.Socket              (SockAddr (..))
+import           Text.Read                   as R
+
+-- | Network address with a timestamp.
+type NetworkAddressTime = (Word32, NetworkAddress)
+
+-- | Provides information about known nodes in the bitcoin network. An 'Addr'
+-- type is sent inside a 'Message' as a response to a 'GetAddr' message.
+newtype Addr =
+    Addr { -- List of addresses of other nodes on the network with timestamps.
+           addrList :: [NetworkAddressTime]
+         }
+    deriving (Eq, Show)
+
+instance Serialize Addr where
+
+    get = Addr <$> (repList =<< S.get)
+      where
+        repList (VarInt c) = replicateM (fromIntegral c) action
+        action             = liftM2 (,) getWord32le S.get
+
+    put (Addr xs) = do
+        put $ VarInt $ fromIntegral $ length xs
+        forM_ xs $ \(a,b) -> putWord32le a >> put b
+
+-- | Data type describing signed messages that can be sent between bitcoin
+-- nodes to display important notifications to end users about the health of
+-- the network.
+data Alert =
+    Alert {
+          -- | Alert payload.
+            alertPayload   :: !VarString
+          -- | ECDSA signature of the payload
+          , alertSignature :: !VarString
+          } deriving (Eq, Show, Read)
+
+instance NFData Alert where
+    rnf (Alert p s) = rnf p `seq` rnf s
+
+instance Serialize Alert where
+    get = Alert <$> S.get <*> S.get
+    put (Alert p s) = put p >> put s
+
+-- | The 'GetData' type is used to retrieve information on a specific object
+-- ('Block' or 'Tx') identified by the objects hash. The payload of a 'GetData'
+-- request is a list of 'InvVector' which represent all the hashes of objects
+-- that a node wants. The response to a 'GetBlock' message will be either a
+-- 'Block' or a 'Tx' message depending on the type of the object referenced by
+-- the hash. Usually, 'GetData' messages are sent after a node receives an 'Inv'
+-- message that contains unknown object hashes.
+newtype GetData =
+    GetData { -- | list of object hashes
+              getDataList :: [InvVector]
+            } deriving (Eq, Show)
+
+instance NFData GetData where
+    rnf (GetData l) = rnf l
+
+instance Serialize GetData where
+
+    get = GetData <$> (repList =<< S.get)
+      where
+        repList (VarInt c) = replicateM (fromIntegral c) S.get
+
+    put (GetData xs) = do
+        put $ VarInt $ fromIntegral $ length xs
+        forM_ xs put
+
+-- | 'Inv' messages are used by nodes to advertise their knowledge of new
+-- objects by publishing a list of hashes to a peer. 'Inv' messages can be sent
+-- unsolicited or in response to a 'GetBlocks' message.
+newtype Inv =
+    Inv {
+        -- | inventory
+          invList :: [InvVector]
+        } deriving (Eq, Show)
+
+instance NFData Inv where
+    rnf (Inv l) = rnf l
+
+instance Serialize Inv where
+
+    get = Inv <$> (repList =<< S.get)
+      where
+        repList (VarInt c) = replicateM (fromIntegral c) S.get
+
+    put (Inv xs) = do
+        put $ VarInt $ fromIntegral $ length xs
+        forM_ xs put
+
+-- | Data type identifying the type of an inventory vector. SegWit types are
+-- only used in 'GetData' messages, not 'Inv'.
+data InvType
+    = InvError -- ^ error
+    | InvTx -- ^ transaction
+    | InvBlock -- ^ block
+    | InvMerkleBlock -- ^ filtered block
+    | InvWitnessTx -- ^ segwit transaction
+    | InvWitnessBlock -- ^ segwit block
+    | InvWitnessMerkleBlock -- ^ segwit filtere block
+    deriving (Eq, Show, Read)
+
+instance NFData InvType where rnf x = seq x ()
+
+instance Serialize InvType where
+    get = go =<< getWord32le
+      where
+        go x =
+            case x of
+                0 -> return InvError
+                1 -> return InvTx
+                2 -> return InvBlock
+                3 -> return InvMerkleBlock
+                _
+                    | x == 1 `shiftL` 30 + 1 -> return InvWitnessTx
+                    | x == 1 `shiftL` 30 + 2 -> return InvWitnessBlock
+                    | x == 1 `shiftL` 30 + 3 -> return InvWitnessMerkleBlock
+                    | otherwise -> fail "bitcoinGet InvType: Invalid Type"
+    put x =
+        putWord32le $
+        case x of
+            InvError              -> 0
+            InvTx                 -> 1
+            InvBlock              -> 2
+            InvMerkleBlock        -> 3
+            InvWitnessTx          -> 1 `shiftL` 30 + 1
+            InvWitnessBlock       -> 1 `shiftL` 30 + 2
+            InvWitnessMerkleBlock -> 1 `shiftL` 30 + 3
+
+-- | Invectory vectors represent hashes identifying objects such as a 'Block' or
+-- a 'Tx'. They notify other peers about new data or data they have otherwise
+-- requested.
+data InvVector =
+    InvVector {
+                -- | type of object
+                invType :: !InvType
+                -- | 256-bit hash of object
+              , invHash :: !Hash256
+              } deriving (Eq, Show)
+
+instance NFData InvVector where
+    rnf (InvVector t h) = rnf t `seq` rnf h
+
+instance Serialize InvVector where
+    get = InvVector <$> S.get <*> S.get
+    put (InvVector t h) = put t >> put h
+
+-- | Data type describing a bitcoin network address. Addresses are stored in
+-- IPv6 format. IPv4 addresses are mapped to IPv6 using IPv4 mapped IPv6
+-- addresses: <http://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses>.
+data NetworkAddress =
+    NetworkAddress { -- | bitmask of services available for this address
+                     naServices :: !Word64
+                     -- | address and port information
+                   , naAddress  :: !SockAddr
+                   } deriving (Eq, Show)
+
+instance NFData NetworkAddress where
+    rnf NetworkAddress{..} = rnf naServices `seq` naAddress `seq` ()
+
+instance Serialize NetworkAddress where
+
+    get = NetworkAddress <$> getWord64le
+                         <*> getAddrPort
+      where
+        getAddrPort = do
+            a <- getWord32be
+            b <- getWord32be
+            c <- getWord32be
+            if a == 0x00000000 && b == 0x00000000 && c == 0x0000ffff
+              then do
+                d <- getWord32host
+                p <- getWord16be
+                return $ SockAddrInet (fromIntegral p) d
+              else do
+                d <- getWord32be
+                p <- getWord16be
+                return $ SockAddrInet6 (fromIntegral p) 0 (a,b,c,d) 0
+
+    put (NetworkAddress s (SockAddrInet6 p _ (a,b,c,d) _)) = do
+        putWord64le s
+        putWord32be a
+        putWord32be b
+        putWord32be c
+        putWord32be d
+        putWord16be (fromIntegral p)
+
+    put (NetworkAddress s (SockAddrInet p a)) = do
+        putWord64le s
+        putWord32be 0x00000000
+        putWord32be 0x00000000
+        putWord32be 0x0000ffff
+        putWord32host a
+        putWord16be (fromIntegral p)
+
+    put _ = error "NetworkAddress can onle be IPv4 or IPv6"
+
+-- | A 'NotFound' message is returned as a response to a 'GetData' message
+-- whe one of the requested objects could not be retrieved. This could happen,
+-- for example, if a tranasaction was requested and was not available in the
+-- memory pool of the receiving node.
+newtype NotFound =
+    NotFound { -- | Inventory vectors related to this request
+               notFoundList :: [InvVector]
+             } deriving (Eq, Show)
+
+instance NFData NotFound where
+    rnf (NotFound l) = rnf l
+
+instance Serialize NotFound where
+
+    get = NotFound <$> (repList =<< S.get)
+      where
+        repList (VarInt c) = replicateM (fromIntegral c) S.get
+
+    put (NotFound xs) = do
+        put $ VarInt $ fromIntegral $ length xs
+        forM_ xs put
+
+-- | A 'Ping' message is sent to bitcoin peers to check if a connection is still
+-- open.
+newtype Ping =
+    Ping { -- | A random nonce used to identify the recipient of the ping
+           -- request once a Pong response is received.
+           pingNonce :: Word64
+         } deriving (Eq, Show, Read)
+
+instance NFData Ping where
+    rnf (Ping n) = rnf n
+
+-- | A Pong message is sent as a response to a ping message.
+newtype Pong =
+    Pong {
+           -- | nonce from corresponding 'Ping'
+           pongNonce :: Word64
+         } deriving (Eq, Show, Read)
+
+instance NFData Pong where
+    rnf (Pong n) = rnf n
+
+instance Serialize Ping where
+    get = Ping <$> getWord64le
+    put (Ping n) = putWord64le n
+
+instance Serialize Pong where
+    get = Pong <$> getWord64le
+    put (Pong n) = putWord64le n
+
+-- | The 'Reject' message is sent when messages are rejected by a peer.
+data Reject =
+    Reject {
+             -- | type of message rejected
+             rejectMessage :: !MessageCommand
+             -- | rejection code
+           , rejectCode    :: !RejectCode
+             -- | text reason for rejection
+           , rejectReason  :: !VarString
+             -- | extra data such as block or tx hash
+           , rejectData    :: !ByteString
+           } deriving (Eq, Show, Read)
+
+
+data RejectCode
+    = RejectMalformed
+    | RejectInvalid
+    | RejectObsolete
+    | RejectDuplicate
+    | RejectNonStandard
+    | RejectDust
+    | RejectInsufficientFee
+    | RejectCheckpoint
+    deriving (Eq, Show, Read)
+
+instance Serialize RejectCode where
+
+    get = getWord8 >>= \code -> case code of
+        0x01 -> return RejectMalformed
+        0x10 -> return RejectInvalid
+        0x11 -> return RejectObsolete
+        0x12 -> return RejectDuplicate
+        0x40 -> return RejectNonStandard
+        0x41 -> return RejectDust
+        0x42 -> return RejectInsufficientFee
+        0x43 -> return RejectCheckpoint
+        _    -> fail $ unwords
+            [ "Reject get: Invalid code"
+            , show code
+            ]
+
+    put code = putWord8 $ case code of
+        RejectMalformed       -> 0x01
+        RejectInvalid         -> 0x10
+        RejectObsolete        -> 0x11
+        RejectDuplicate       -> 0x12
+        RejectNonStandard     -> 0x40
+        RejectDust            -> 0x41
+        RejectInsufficientFee -> 0x42
+        RejectCheckpoint      -> 0x43
+
+-- | Convenience function to build a 'Reject' message.
+reject :: MessageCommand -> RejectCode -> ByteString -> Reject
+reject cmd code reason =
+    Reject cmd code (VarString reason) B.empty
+
+instance Serialize Reject where
+
+    get = S.get >>= \(VarString bs) -> case stringToCommand bs of
+        Just cmd -> Reject cmd <$> S.get <*> S.get <*> maybeData
+        _ -> fail $ unwords
+            ["Reason get: Invalid message command" ,cs bs]
+      where
+        maybeData = isEmpty >>= \done ->
+            if done then return B.empty else getByteString 32
+
+    put (Reject cmd code reason dat) = do
+        put $ VarString $ commandToString cmd
+        put code
+        put reason
+        unless (B.null dat) $ putByteString dat
+
+-- | Data type representing a variable-length integer. The 'VarInt' type
+-- usually precedes an array or a string that can vary in length.
+newtype VarInt = VarInt { getVarInt :: Word64 }
+    deriving (Eq, Show, Read)
+
+instance NFData VarInt where
+    rnf (VarInt w) = rnf w
+
+instance Serialize VarInt where
+
+    get = VarInt <$> ( getWord8 >>= go )
+      where
+        go 0xff = getWord64le
+        go 0xfe = fromIntegral <$> getWord32le
+        go 0xfd = fromIntegral <$> getWord16le
+        go x    = fromIntegral <$> return x
+
+    put (VarInt x)
+        | x < 0xfd =
+            putWord8 $ fromIntegral x
+        | x <= 0xffff = do
+            putWord8 0xfd
+            putWord16le $ fromIntegral x
+        | x <= 0xffffffff = do
+            putWord8 0xfe
+            putWord32le $ fromIntegral x
+        | otherwise = do
+            putWord8 0xff
+            putWord64le x
+
+-- | Data type for serialization of variable-length strings.
+newtype VarString = VarString { getVarString :: ByteString }
+    deriving (Eq, Show, Read)
+
+instance NFData VarString where
+    rnf (VarString s) = rnf s
+
+instance Serialize VarString where
+
+    get = VarString <$> (readBS =<< S.get)
+      where
+        readBS (VarInt len) = getByteString (fromIntegral len)
+
+    put (VarString bs) = do
+        put $ VarInt $ fromIntegral $ B.length bs
+        putByteString bs
+
+-- | When a bitcoin node creates an outgoing connection to another node,
+-- the first message it will send is a 'Version' message. The other node
+-- will similarly respond with it's own 'Version' message.
+data Version =
+    Version {
+              -- | protocol version
+              version     :: !Word32
+              -- | features supported by this connection
+            , services    :: !Word64
+              -- | unix timestamp
+            , timestamp   :: !Word64
+              -- | network address of remote node
+            , addrRecv    :: !NetworkAddress
+              -- | network address of sending node
+            , addrSend    :: !NetworkAddress
+              -- | random nonce to detect connection to self
+            , verNonce    :: !Word64
+              -- | user agent string
+            , userAgent   :: !VarString
+              -- | height of the last block in sending node
+            , startHeight :: !Word32
+              -- | relay transactions flag (BIP-37)
+            , relay       :: !Bool
+            } deriving (Eq, Show)
+
+instance NFData Version where
+    rnf Version{..} =
+        rnf version `seq`
+        rnf services `seq`
+        rnf timestamp `seq`
+        rnf addrRecv `seq`
+        rnf addrSend `seq`
+        rnf verNonce `seq`
+        rnf userAgent `seq`
+        rnf startHeight `seq`
+        rnf relay
+
+instance Serialize Version where
+
+    get = Version <$> getWord32le
+                  <*> getWord64le
+                  <*> getWord64le
+                  <*> S.get
+                  <*> S.get
+                  <*> getWord64le
+                  <*> S.get
+                  <*> getWord32le
+                  <*> (go =<< isEmpty)
+      where
+        go True  = return True
+        go False = getBool
+
+    put (Version v s t ar as n ua sh r) = do
+        putWord32le v
+        putWord64le s
+        putWord64le t
+        put         ar
+        put         as
+        putWord64le n
+        put         ua
+        putWord32le sh
+        putBool     r
+
+-- | 0x00 is 'False', anything else is 'True'.
+getBool :: Get Bool
+getBool = go =<< getWord8
+  where
+    go 0 = return False
+    go _ = return True
+
+putBool :: Bool -> Put
+putBool True  = putWord8 1
+putBool False = putWord8 0
+
+-- | A 'MessageCommand' is included in a 'MessageHeader' in order to identify
+-- the type of message present in the payload. This allows the message
+-- de-serialization code to know how to decode a particular message payload.
+-- Every valid 'Message' constructor has a corresponding 'MessageCommand'
+-- constructor.
+data MessageCommand
+    = MCVersion
+    | MCVerAck
+    | MCAddr
+    | MCInv
+    | MCGetData
+    | MCNotFound
+    | MCGetBlocks
+    | MCGetHeaders
+    | MCTx
+    | MCBlock
+    | MCMerkleBlock
+    | MCHeaders
+    | MCGetAddr
+    | MCFilterLoad
+    | MCFilterAdd
+    | MCFilterClear
+    | MCPing
+    | MCPong
+    | MCAlert
+    | MCMempool
+    | MCReject
+    | MCSendHeaders
+    deriving (Eq)
+
+instance Show MessageCommand where
+    showsPrec _ = shows . commandToString
+
+instance Read MessageCommand where
+    readPrec = do
+        String str <- lexP
+        maybe pfail return (stringToCommand (cs str))
+
+instance NFData MessageCommand where rnf x = seq x ()
+
+instance Serialize MessageCommand where
+    get = go =<< getByteString 12
+      where
+        go bs =
+            let str = unpackCommand bs
+            in case stringToCommand str of
+                Just cmd -> return cmd
+                Nothing  -> fail $ cs $
+                    "get MessageCommand: Invalid command: " <> str
+    put mc = putByteString $ packCommand $ commandToString mc
+
+instance IsString MessageCommand where
+    fromString str =
+        fromMaybe
+            (error ("Could not recognize message command " <> str))
+            (stringToCommand (cs str))
+
+-- | Read a 'MessageCommand' from its string representation.
+stringToCommand :: ByteString -> Maybe MessageCommand
+stringToCommand str = case str of
+    "version"     -> Just MCVersion
+    "verack"      -> Just MCVerAck
+    "addr"        -> Just MCAddr
+    "inv"         -> Just MCInv
+    "getdata"     -> Just MCGetData
+    "notfound"    -> Just MCNotFound
+    "getblocks"   -> Just MCGetBlocks
+    "getheaders"  -> Just MCGetHeaders
+    "tx"          -> Just MCTx
+    "block"       -> Just MCBlock
+    "merkleblock" -> Just MCMerkleBlock
+    "headers"     -> Just MCHeaders
+    "getaddr"     -> Just MCGetAddr
+    "filterload"  -> Just MCFilterLoad
+    "filteradd"   -> Just MCFilterAdd
+    "filterclear" -> Just MCFilterClear
+    "ping"        -> Just MCPing
+    "pong"        -> Just MCPong
+    "alert"       -> Just MCAlert
+    "mempool"     -> Just MCMempool
+    "reject"      -> Just MCReject
+    "sendheaders" -> Just MCSendHeaders
+    _             -> Nothing
+
+-- | Convert a 'MessageCommand' to its string representation.
+commandToString :: MessageCommand -> ByteString
+commandToString mc = case mc of
+    MCVersion     -> "version"
+    MCVerAck      -> "verack"
+    MCAddr        -> "addr"
+    MCInv         -> "inv"
+    MCGetData     -> "getdata"
+    MCNotFound    -> "notfound"
+    MCGetBlocks   -> "getblocks"
+    MCGetHeaders  -> "getheaders"
+    MCTx          -> "tx"
+    MCBlock       -> "block"
+    MCMerkleBlock -> "merkleblock"
+    MCHeaders     -> "headers"
+    MCGetAddr     -> "getaddr"
+    MCFilterLoad  -> "filterload"
+    MCFilterAdd   -> "filteradd"
+    MCFilterClear -> "filterclear"
+    MCPing        -> "ping"
+    MCPong        -> "pong"
+    MCAlert       -> "alert"
+    MCMempool     -> "mempool"
+    MCReject      -> "reject"
+    MCSendHeaders -> "sendheaders"
+
+-- | Pack a string 'MessageCommand' so that it is exactly 12-bytes long.
+packCommand :: ByteString -> ByteString
+packCommand s = B.take 12 $
+    s `mappend` C.replicate 12 '\NUL'
+
+-- | Undo packing done by 'packCommand'.
+unpackCommand :: ByteString -> ByteString
+unpackCommand = B.takeWhile (/= 0)
+
+-- | Node offers no services.
+nodeNone :: Word64
+nodeNone = 0
+
+-- | Services indicate node is a full node that can serve full blocks.
+nodeNetwork :: Word64
+nodeNetwork = 1
+
+-- | Services indicate node allows to request 'UTXO' set.
+nodeGetUTXO :: Word64
+nodeGetUTXO = 1 `shiftL` 1
+
+-- | Services indicate node accepts bloom filters.
+nodeBloom :: Word64
+nodeBloom = 1 `shiftL` 2
+
+-- | Services indicate SegWit-capable node.
+nodeWitness :: Word64
+nodeWitness = 1 `shiftL` 3
+
+-- | Services indicate Xtreme Thinblocks compatibility.
+nodeXThin :: Word64
+nodeXThin = 1 `shiftL` 4
diff --git a/src/Network/Haskoin/Network/Message.hs b/src/Network/Haskoin/Network/Message.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Network/Message.hs
@@ -0,0 +1,186 @@
+module Network.Haskoin.Network.Message
+    ( -- * Network Message
+      Message(..)
+    , MessageHeader(..)
+    , msgType
+    , putMessage
+    , getMessage
+    ) where
+
+import           Control.DeepSeq                    (NFData, rnf)
+import           Control.Monad                      (unless)
+import qualified Data.ByteString                    as BS
+import           Data.Serialize                     (Serialize, encode, get,
+                                                     put)
+import           Data.Serialize.Get                 (Get, getByteString,
+                                                     getWord32be, getWord32le,
+                                                     isolate, lookAhead)
+import           Data.Serialize.Put                 (Putter, putByteString,
+                                                     putWord32be, putWord32le)
+import           Data.Word                          (Word32)
+import           Network.Haskoin.Block.Common
+import           Network.Haskoin.Block.Merkle
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Network.Bloom
+import           Network.Haskoin.Network.Common
+import           Network.Haskoin.Transaction.Common
+
+-- | Data type representing the header of a 'Message'. All messages sent between
+-- nodes contain a message header.
+data MessageHeader = MessageHeader
+    { -- | magic bytes identify network
+      headMagic       :: !Word32
+      -- | message type
+    , headCmd         :: !MessageCommand
+      -- | length of payload
+    , headPayloadSize :: !Word32
+      -- | checksum of payload
+    , headChecksum    :: !CheckSum32
+    } deriving (Eq, Show)
+
+instance NFData MessageHeader where
+    rnf (MessageHeader m c p s) = rnf m `seq` rnf c `seq` rnf p `seq` rnf s
+
+instance Serialize MessageHeader where
+
+    get = MessageHeader <$> getWord32be
+                        <*> get
+                        <*> getWord32le
+                        <*> get
+
+    put (MessageHeader m c l chk) = do
+        putWord32be m
+        put         c
+        putWord32le l
+        put         chk
+
+-- | The 'Message' type is used to identify all the valid messages that can be
+-- sent between bitcoin peers. Only values of type 'Message' will be accepted
+-- by other bitcoin peers as bitcoin protocol messages need to be correctly
+-- serialized with message headers. Serializing a 'Message' value will
+-- include the 'MessageHeader' with the correct checksum value automatically.
+-- No need to add the 'MessageHeader' separately.
+data Message
+    = MVersion !Version
+    | MVerAck
+    | MAddr !Addr
+    | MInv !Inv
+    | MGetData !GetData
+    | MNotFound !NotFound
+    | MGetBlocks !GetBlocks
+    | MGetHeaders !GetHeaders
+    | MTx !Tx
+    | MBlock !Block
+    | MMerkleBlock !MerkleBlock
+    | MHeaders !Headers
+    | MGetAddr
+    | MFilterLoad !FilterLoad
+    | MFilterAdd !FilterAdd
+    | MFilterClear
+    | MPing !Ping
+    | MPong !Pong
+    | MAlert !Alert
+    | MMempool
+    | MReject !Reject
+    | MSendHeaders
+    deriving (Eq, Show)
+
+-- | Get 'MessageCommand' assocated with a message.
+msgType :: Message -> MessageCommand
+msgType (MVersion _)     = MCVersion
+msgType MVerAck          = MCVerAck
+msgType (MAddr _)        = MCAddr
+msgType (MInv _)         = MCInv
+msgType (MGetData _)     = MCGetData
+msgType (MNotFound _)    = MCNotFound
+msgType (MGetBlocks _)   = MCGetBlocks
+msgType (MGetHeaders _)  = MCGetHeaders
+msgType (MTx _)          = MCTx
+msgType (MBlock _)       = MCBlock
+msgType (MMerkleBlock _) = MCMerkleBlock
+msgType (MHeaders _)     = MCHeaders
+
+msgType (MFilterLoad _)  = MCFilterLoad
+msgType (MFilterAdd _)   = MCFilterAdd
+msgType MFilterClear     = MCFilterClear
+msgType (MPing _)        = MCPing
+msgType (MPong _)        = MCPong
+msgType (MAlert _)       = MCAlert
+msgType MMempool         = MCMempool
+msgType (MReject _)      = MCReject
+msgType MSendHeaders     = MCSendHeaders
+msgType MGetAddr         = MCGetAddr
+
+-- | Deserializer for network messages.
+getMessage :: Network -> Get Message
+getMessage net = do
+    (MessageHeader mgc cmd len chk) <- get
+    bs <- lookAhead $ getByteString $ fromIntegral len
+    unless
+        (mgc == getNetworkMagic net)
+        (fail $ "get: Invalid network magic bytes: " ++ show mgc)
+    unless
+        (checkSum32 bs == chk)
+        (fail $ "get: Invalid message checksum: " ++ show chk)
+    if len > 0
+        then isolate (fromIntegral len) $
+             case cmd of
+                 MCVersion     -> MVersion <$> get
+                 MCAddr        -> MAddr <$> get
+                 MCInv         -> MInv <$> get
+                 MCGetData     -> MGetData <$> get
+                 MCNotFound    -> MNotFound <$> get
+                 MCGetBlocks   -> MGetBlocks <$> get
+                 MCGetHeaders  -> MGetHeaders <$> get
+                 MCTx          -> MTx <$> get
+                 MCBlock       -> MBlock <$> get
+                 MCMerkleBlock -> MMerkleBlock <$> get
+                 MCHeaders     -> MHeaders <$> get
+                 MCFilterLoad  -> MFilterLoad <$> get
+                 MCFilterAdd   -> MFilterAdd <$> get
+                 MCPing        -> MPing <$> get
+                 MCPong        -> MPong <$> get
+                 MCAlert       -> MAlert <$> get
+                 MCReject      -> MReject <$> get
+                 _             -> fail $ "get: Invalid command " ++ show cmd
+        else case cmd of
+                 MCGetAddr     -> return MGetAddr
+                 MCVerAck      -> return MVerAck
+                 MCFilterClear -> return MFilterClear
+                 MCMempool     -> return MMempool
+                 MCSendHeaders -> return MSendHeaders
+                 _             -> fail $ "get: Invalid command " ++ show cmd
+
+-- | Serializer for network messages.
+putMessage :: Network -> Putter Message
+putMessage net msg = do
+    let (cmd, payload) =
+            case msg of
+                MVersion m     -> (MCVersion, encode m)
+                MVerAck        -> (MCVerAck, BS.empty)
+                MAddr m        -> (MCAddr, encode m)
+                MInv m         -> (MCInv, encode m)
+                MGetData m     -> (MCGetData, encode m)
+                MNotFound m    -> (MCNotFound, encode m)
+                MGetBlocks m   -> (MCGetBlocks, encode m)
+                MGetHeaders m  -> (MCGetHeaders, encode m)
+                MTx m          -> (MCTx, encode m)
+                MBlock m       -> (MCBlock, encode m)
+                MMerkleBlock m -> (MCMerkleBlock, encode m)
+                MHeaders m     -> (MCHeaders, encode m)
+                MGetAddr       -> (MCGetAddr, BS.empty)
+                MFilterLoad m  -> (MCFilterLoad, encode m)
+                MFilterAdd m   -> (MCFilterAdd, encode m)
+                MFilterClear   -> (MCFilterClear, BS.empty)
+                MPing m        -> (MCPing, encode m)
+                MPong m        -> (MCPong, encode m)
+                MAlert m       -> (MCAlert, encode m)
+                MMempool       -> (MCMempool, BS.empty)
+                MReject m      -> (MCReject, encode m)
+                MSendHeaders   -> (MCSendHeaders, BS.empty)
+        chk = checkSum32 payload
+        len = fromIntegral $ BS.length payload
+        header = MessageHeader (getNetworkMagic net) cmd len chk
+    put header
+    putByteString payload
diff --git a/src/Network/Haskoin/Script.hs b/src/Network/Haskoin/Script.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Script.hs
@@ -0,0 +1,12 @@
+{-|
+  This package provides functions for parsing and evaluating bitcoin
+  transaction scripts. Data types are provided for building and
+  deconstructing all of the standard input and output script types.
+-}
+module Network.Haskoin.Script
+    ( module X
+    ) where
+
+import           Network.Haskoin.Script.Common   as X
+import           Network.Haskoin.Script.SigHash  as X
+import           Network.Haskoin.Script.Standard as X
diff --git a/src/Network/Haskoin/Script/Common.hs b/src/Network/Haskoin/Script/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Script/Common.hs
@@ -0,0 +1,709 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Script.Common
+( ScriptOp(..)
+, Script(..)
+, PushDataType(..)
+, ScriptOutput(..)
+, isPayPK
+, isPayPKHash
+, isPayMulSig
+, isPayScriptHash
+, isPayWitnessPKHash
+, isPayWitnessScriptHash
+, isDataCarrier
+, encodeOutput
+, encodeOutputBS
+, decodeOutput
+, decodeOutputBS
+, isPushOp
+, opPushData
+, intToScriptOp
+, scriptOpToInt
+) where
+
+import           Control.DeepSeq                    (NFData, rnf)
+import           Control.Monad
+import           Data.Aeson                         as A
+import           Data.ByteString                    (ByteString)
+import qualified Data.ByteString                    as B
+import           Data.Serialize                     as S
+import           Data.Serialize.Get                 (getByteString, getWord16le,
+                                                     getWord32le, getWord8,
+                                                     isEmpty)
+import           Data.Serialize.Put                 (putByteString, putWord16le,
+                                                     putWord32le, putWord8)
+import           Data.String.Conversions
+import           Data.Word                          (Word8)
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Keys.Common
+import           Network.Haskoin.Util
+
+-- | Data type representing a transaction script. Scripts are defined as lists
+-- of script operators 'ScriptOp'. Scripts are used to:
+--
+-- * Define the spending conditions in the output of a transaction.
+-- * Provide signatures in the input of a transaction (except SegWit).
+--
+-- SigWit only: the segregated witness data structure, and not the input script,
+-- contains signatures and redeem script for pay-to-witness-script and
+-- pay-to-witness-public-key-hash transactions.
+newtype Script =
+    Script {
+             -- | script operators defining this script
+             scriptOps :: [ScriptOp]
+           }
+    deriving (Eq, Show, Read)
+
+instance NFData Script where
+    rnf (Script o) = rnf o
+
+instance Serialize Script where
+    get =
+        Script <$> getScriptOps
+      where
+        getScriptOps = do
+            empty <- isEmpty
+            if empty
+                then return []
+                else (:) <$> get <*> getScriptOps
+
+    put (Script ops) = forM_ ops put
+
+-- | Data type representing the type of an OP_PUSHDATA opcode.
+data PushDataType
+    =
+      -- | next opcode bytes is data to be pushed
+      OPCODE
+      -- | next byte contains number of bytes of data to be pushed
+    | OPDATA1
+      -- | next two bytes contains number of bytes to be pushed
+    | OPDATA2
+      -- | next four bytes contains the number of bytes to be pushed
+    | OPDATA4
+    deriving (Show, Read, Eq)
+
+instance NFData PushDataType where rnf x = seq x ()
+
+-- | Data type representing an operator allowed inside a 'Script'.
+data ScriptOp
+      -- Pushing Data
+    = OP_PUSHDATA !ByteString !PushDataType
+    | OP_0
+    | OP_1NEGATE
+    | OP_RESERVED
+    | OP_1  | OP_2  | OP_3  | OP_4
+    | OP_5  | OP_6  | OP_7  | OP_8
+    | OP_9  | OP_10 | OP_11 | OP_12
+    | OP_13 | OP_14 | OP_15 | OP_16
+
+      -- Flow control
+    | OP_NOP
+    | OP_VER        -- reserved
+    | OP_IF
+    | OP_NOTIF
+    | OP_VERIF      -- resreved
+    | OP_VERNOTIF   -- reserved
+    | OP_ELSE
+    | OP_ENDIF
+    | OP_VERIFY
+    | OP_RETURN
+
+      -- Stack operations
+    | OP_TOALTSTACK
+    | OP_FROMALTSTACK
+    | OP_IFDUP
+    | OP_DEPTH
+    | OP_DROP
+    | OP_DUP
+    | OP_NIP
+    | OP_OVER
+    | OP_PICK
+    | OP_ROLL
+    | OP_ROT
+    | OP_SWAP
+    | OP_TUCK
+    | OP_2DROP
+    | OP_2DUP
+    | OP_3DUP
+    | OP_2OVER
+    | OP_2ROT
+    | OP_2SWAP
+
+      -- Splice
+    | OP_CAT
+    | OP_SUBSTR
+    | OP_LEFT
+    | OP_RIGHT
+    | OP_SIZE
+
+      -- Bitwise logic
+    | OP_INVERT
+    | OP_AND
+    | OP_OR
+    | OP_XOR
+    | OP_EQUAL
+    | OP_EQUALVERIFY
+    | OP_RESERVED1
+    | OP_RESERVED2
+
+      -- Arithmetic
+    | OP_1ADD
+    | OP_1SUB
+    | OP_2MUL
+    | OP_2DIV
+    | OP_NEGATE
+    | OP_ABS
+    | OP_NOT
+    | OP_0NOTEQUAL
+    | OP_ADD
+    | OP_SUB
+    | OP_MUL
+    | OP_DIV
+    | OP_MOD
+    | OP_LSHIFT
+    | OP_RSHIFT
+    | OP_BOOLAND
+    | OP_BOOLOR
+    | OP_NUMEQUAL
+    | OP_NUMEQUALVERIFY
+    | OP_NUMNOTEQUAL
+    | OP_LESSTHAN
+    | OP_GREATERTHAN
+    | OP_LESSTHANOREQUAL
+    | OP_GREATERTHANOREQUAL
+    | OP_MIN
+    | OP_MAX
+    | OP_WITHIN
+
+      -- Crypto
+    | OP_RIPEMD160
+    | OP_SHA1
+    | OP_SHA256
+    | OP_HASH160
+    | OP_HASH256
+    | OP_CODESEPARATOR
+    | OP_CHECKSIG
+    | OP_CHECKSIGVERIFY
+    | OP_CHECKMULTISIG
+    | OP_CHECKMULTISIGVERIFY
+
+      -- Expansion
+    | OP_NOP1 | OP_NOP2 | OP_NOP3 | OP_NOP4 | OP_NOP5
+    | OP_NOP6 | OP_NOP7 | OP_NOP8 | OP_NOP9 | OP_NOP10
+
+
+      -- Other
+    | OP_PUBKEYHASH
+    | OP_PUBKEY
+    | OP_INVALIDOPCODE !Word8
+
+        deriving (Show, Read, Eq)
+
+
+instance NFData ScriptOp where
+    rnf (OP_PUSHDATA b t)    = rnf b `seq` rnf t
+    rnf (OP_INVALIDOPCODE c) = rnf c
+    rnf x                    = x `seq` ()
+
+
+instance Serialize ScriptOp where
+
+    get = go =<< (fromIntegral <$> getWord8)
+      where
+        go op
+            | op == 0x00 = return OP_0
+            | op <= 0x4b = do
+                payload <- getByteString (fromIntegral op)
+                return $ OP_PUSHDATA payload OPCODE
+            | op == 0x4c = do
+                len  <- getWord8
+                payload <- getByteString (fromIntegral len)
+                return $ OP_PUSHDATA payload OPDATA1
+            | op == 0x4d = do
+                len  <- getWord16le
+                payload <- getByteString (fromIntegral len)
+                return $ OP_PUSHDATA payload OPDATA2
+            | op == 0x4e = do
+                len  <- getWord32le
+                payload <- getByteString (fromIntegral len)
+                return $ OP_PUSHDATA payload OPDATA4
+
+            | op == 0x4f = return OP_1NEGATE
+            | op == 0x50 = return OP_RESERVED
+            | op == 0x51 = return OP_1
+            | op == 0x52 = return OP_2
+            | op == 0x53 = return OP_3
+            | op == 0x54 = return OP_4
+            | op == 0x55 = return OP_5
+            | op == 0x56 = return OP_6
+            | op == 0x57 = return OP_7
+            | op == 0x58 = return OP_8
+            | op == 0x59 = return OP_9
+            | op == 0x5a = return OP_10
+            | op == 0x5b = return OP_11
+            | op == 0x5c = return OP_12
+            | op == 0x5d = return OP_13
+            | op == 0x5e = return OP_14
+            | op == 0x5f = return OP_15
+            | op == 0x60 = return OP_16
+            -- Flow control
+            | op == 0x61 = return OP_NOP
+            | op == 0x62 = return OP_VER        -- reserved
+            | op == 0x63 = return OP_IF
+            | op == 0x64 = return OP_NOTIF
+            | op == 0x65 = return OP_VERIF      -- reserved
+            | op == 0x66 = return OP_VERNOTIF   -- reserved
+            | op == 0x67 = return OP_ELSE
+            | op == 0x68 = return OP_ENDIF
+            | op == 0x69 = return OP_VERIFY
+            | op == 0x6a = return OP_RETURN
+
+            -- Stack
+            | op == 0x6b = return OP_TOALTSTACK
+            | op == 0x6c = return OP_FROMALTSTACK
+            | op == 0x6d = return OP_2DROP
+            | op == 0x6e = return OP_2DUP
+            | op == 0x6f = return OP_3DUP
+            | op == 0x70 = return OP_2OVER
+            | op == 0x71 = return OP_2ROT
+            | op == 0x72 = return OP_2SWAP
+            | op == 0x73 = return OP_IFDUP
+            | op == 0x74 = return OP_DEPTH
+            | op == 0x75 = return OP_DROP
+            | op == 0x76 = return OP_DUP
+            | op == 0x77 = return OP_NIP
+            | op == 0x78 = return OP_OVER
+            | op == 0x79 = return OP_PICK
+            | op == 0x7a = return OP_ROLL
+            | op == 0x7b = return OP_ROT
+            | op == 0x7c = return OP_SWAP
+            | op == 0x7d = return OP_TUCK
+
+            -- Splice
+            | op == 0x7e = return OP_CAT
+            | op == 0x7f = return OP_SUBSTR
+            | op == 0x80 = return OP_LEFT
+            | op == 0x81 = return OP_RIGHT
+            | op == 0x82 = return OP_SIZE
+
+            -- Bitwise logic
+            | op == 0x83 = return OP_INVERT
+            | op == 0x84 = return OP_AND
+            | op == 0x85 = return OP_OR
+            | op == 0x86 = return OP_XOR
+            | op == 0x87 = return OP_EQUAL
+            | op == 0x88 = return OP_EQUALVERIFY
+            | op == 0x89 = return OP_RESERVED1
+            | op == 0x8a = return OP_RESERVED2
+
+            -- Arithmetic
+            | op == 0x8b = return OP_1ADD
+            | op == 0x8c = return OP_1SUB
+            | op == 0x8d = return OP_2MUL
+            | op == 0x8e = return OP_2DIV
+            | op == 0x8f = return OP_NEGATE
+            | op == 0x90 = return OP_ABS
+            | op == 0x91 = return OP_NOT
+            | op == 0x92 = return OP_0NOTEQUAL
+            | op == 0x93 = return OP_ADD
+            | op == 0x94 = return OP_SUB
+            | op == 0x95 = return OP_MUL
+            | op == 0x96 = return OP_DIV
+            | op == 0x97 = return OP_MOD
+            | op == 0x98 = return OP_LSHIFT
+            | op == 0x99 = return OP_RSHIFT
+            | op == 0x9a = return OP_BOOLAND
+            | op == 0x9b = return OP_BOOLOR
+            | op == 0x9c = return OP_NUMEQUAL
+            | op == 0x9d = return OP_NUMEQUALVERIFY
+            | op == 0x9e = return OP_NUMNOTEQUAL
+            | op == 0x9f = return OP_LESSTHAN
+            | op == 0xa0 = return OP_GREATERTHAN
+            | op == 0xa1 = return OP_LESSTHANOREQUAL
+            | op == 0xa2 = return OP_GREATERTHANOREQUAL
+            | op == 0xa3 = return OP_MIN
+            | op == 0xa4 = return OP_MAX
+            | op == 0xa5 = return OP_WITHIN
+
+            -- Crypto
+            | op == 0xa6 = return OP_RIPEMD160
+            | op == 0xa7 = return OP_SHA1
+            | op == 0xa8 = return OP_SHA256
+            | op == 0xa9 = return OP_HASH160
+            | op == 0xaa = return OP_HASH256
+            | op == 0xab = return OP_CODESEPARATOR
+            | op == 0xac = return OP_CHECKSIG
+            | op == 0xad = return OP_CHECKSIGVERIFY
+            | op == 0xae = return OP_CHECKMULTISIG
+            | op == 0xaf = return OP_CHECKMULTISIGVERIFY
+
+            -- More NOPs
+            | op == 0xb0 = return OP_NOP1
+            | op == 0xb1 = return OP_NOP2
+            | op == 0xb2 = return OP_NOP3
+            | op == 0xb3 = return OP_NOP4
+            | op == 0xb4 = return OP_NOP5
+            | op == 0xb5 = return OP_NOP6
+            | op == 0xb6 = return OP_NOP7
+            | op == 0xb7 = return OP_NOP8
+            | op == 0xb8 = return OP_NOP9
+            | op == 0xb9 = return OP_NOP10
+
+            -- Constants
+            | op == 0xfd = return OP_PUBKEYHASH
+            | op == 0xfe = return OP_PUBKEY
+
+            | otherwise = return $ OP_INVALIDOPCODE op
+
+    put op = case op of
+
+        (OP_PUSHDATA payload optype)-> do
+            let len = B.length payload
+            case optype of
+                OPCODE -> do
+                    unless (len <= 0x4b) $ fail
+                        "OP_PUSHDATA OPCODE: Payload size too big"
+                    putWord8 $ fromIntegral len
+                OPDATA1 -> do
+                    unless (len <= 0xff) $ fail
+                        "OP_PUSHDATA OPDATA1: Payload size too big"
+                    putWord8 0x4c
+                    putWord8 $ fromIntegral len
+                OPDATA2 -> do
+                    unless (len <= 0xffff) $ fail
+                        "OP_PUSHDATA OPDATA2: Payload size too big"
+                    putWord8 0x4d
+                    putWord16le $ fromIntegral len
+                OPDATA4 -> do
+                    unless (len <= 0x7fffffff) $ fail
+                        "OP_PUSHDATA OPDATA4: Payload size too big"
+                    putWord8 0x4e
+                    putWord32le $ fromIntegral len
+            putByteString payload
+
+        -- Constants
+        OP_0                 -> putWord8 0x00
+        OP_1NEGATE           -> putWord8 0x4f
+        OP_RESERVED          -> putWord8 0x50
+        OP_1                 -> putWord8 0x51
+        OP_2                 -> putWord8 0x52
+        OP_3                 -> putWord8 0x53
+        OP_4                 -> putWord8 0x54
+        OP_5                 -> putWord8 0x55
+        OP_6                 -> putWord8 0x56
+        OP_7                 -> putWord8 0x57
+        OP_8                 -> putWord8 0x58
+        OP_9                 -> putWord8 0x59
+        OP_10                -> putWord8 0x5a
+        OP_11                -> putWord8 0x5b
+        OP_12                -> putWord8 0x5c
+        OP_13                -> putWord8 0x5d
+        OP_14                -> putWord8 0x5e
+        OP_15                -> putWord8 0x5f
+        OP_16                -> putWord8 0x60
+
+        -- Crypto Constants
+        OP_PUBKEY            -> putWord8 0xfe
+        OP_PUBKEYHASH        -> putWord8 0xfd
+
+        -- Invalid Opcodes
+        (OP_INVALIDOPCODE x) -> putWord8 x
+
+        -- Flow Control
+        OP_NOP               -> putWord8 0x61
+        OP_VER               -> putWord8 0x62
+        OP_IF                -> putWord8 0x63
+        OP_NOTIF             -> putWord8 0x64
+        OP_VERIF             -> putWord8 0x65
+        OP_VERNOTIF          -> putWord8 0x66
+        OP_ELSE              -> putWord8 0x67
+        OP_ENDIF             -> putWord8 0x68
+        OP_VERIFY            -> putWord8 0x69
+        OP_RETURN            -> putWord8 0x6a
+
+        -- Stack Operations
+        OP_TOALTSTACK        -> putWord8 0x6b
+        OP_FROMALTSTACK      -> putWord8 0x6c
+        OP_2DROP             -> putWord8 0x6d
+        OP_2DUP              -> putWord8 0x6e
+        OP_3DUP              -> putWord8 0x6f
+        OP_2OVER             -> putWord8 0x70
+        OP_2ROT              -> putWord8 0x71
+        OP_2SWAP             -> putWord8 0x72
+        OP_IFDUP             -> putWord8 0x73
+        OP_DEPTH             -> putWord8 0x74
+        OP_DROP              -> putWord8 0x75
+        OP_DUP               -> putWord8 0x76
+        OP_NIP               -> putWord8 0x77
+        OP_OVER              -> putWord8 0x78
+        OP_PICK              -> putWord8 0x79
+        OP_ROLL              -> putWord8 0x7a
+        OP_ROT               -> putWord8 0x7b
+        OP_SWAP              -> putWord8 0x7c
+        OP_TUCK              -> putWord8 0x7d
+
+        -- Splice
+        OP_CAT               -> putWord8 0x7e
+        OP_SUBSTR            -> putWord8 0x7f
+        OP_LEFT              -> putWord8 0x80
+        OP_RIGHT             -> putWord8 0x81
+        OP_SIZE              -> putWord8 0x82
+
+        -- Bitwise Logic
+        OP_INVERT            -> putWord8 0x83
+        OP_AND               -> putWord8 0x84
+        OP_OR                -> putWord8 0x85
+        OP_XOR               -> putWord8 0x86
+        OP_EQUAL             -> putWord8 0x87
+        OP_EQUALVERIFY       -> putWord8 0x88
+        OP_RESERVED1         -> putWord8 0x89
+        OP_RESERVED2         -> putWord8 0x8a
+
+        -- Arithmetic
+        OP_1ADD              -> putWord8 0x8b
+        OP_1SUB              -> putWord8 0x8c
+        OP_2MUL              -> putWord8 0x8d
+        OP_2DIV              -> putWord8 0x8e
+        OP_NEGATE            -> putWord8 0x8f
+        OP_ABS               -> putWord8 0x90
+        OP_NOT               -> putWord8 0x91
+        OP_0NOTEQUAL         -> putWord8 0x92
+        OP_ADD               -> putWord8 0x93
+        OP_SUB               -> putWord8 0x94
+        OP_MUL               -> putWord8 0x95
+        OP_DIV               -> putWord8 0x96
+        OP_MOD               -> putWord8 0x97
+        OP_LSHIFT            -> putWord8 0x98
+        OP_RSHIFT            -> putWord8 0x99
+        OP_BOOLAND           -> putWord8 0x9a
+        OP_BOOLOR            -> putWord8 0x9b
+        OP_NUMEQUAL          -> putWord8 0x9c
+        OP_NUMEQUALVERIFY    -> putWord8 0x9d
+        OP_NUMNOTEQUAL       -> putWord8 0x9e
+        OP_LESSTHAN          -> putWord8 0x9f
+        OP_GREATERTHAN       -> putWord8 0xa0
+        OP_LESSTHANOREQUAL   -> putWord8 0xa1
+        OP_GREATERTHANOREQUAL-> putWord8 0xa2
+        OP_MIN               -> putWord8 0xa3
+        OP_MAX               -> putWord8 0xa4
+        OP_WITHIN            -> putWord8 0xa5
+
+        -- Crypto
+        OP_RIPEMD160         -> putWord8 0xa6
+        OP_SHA1              -> putWord8 0xa7
+        OP_SHA256            -> putWord8 0xa8
+        OP_HASH160           -> putWord8 0xa9
+        OP_HASH256           -> putWord8 0xaa
+        OP_CODESEPARATOR     -> putWord8 0xab
+        OP_CHECKSIG          -> putWord8 0xac
+        OP_CHECKSIGVERIFY    -> putWord8 0xad
+        OP_CHECKMULTISIG     -> putWord8 0xae
+        OP_CHECKMULTISIGVERIFY -> putWord8 0xaf
+
+        -- More NOPs
+        OP_NOP1              -> putWord8 0xb0
+        OP_NOP2              -> putWord8 0xb1
+        OP_NOP3              -> putWord8 0xb2
+        OP_NOP4              -> putWord8 0xb3
+        OP_NOP5              -> putWord8 0xb4
+        OP_NOP6              -> putWord8 0xb5
+        OP_NOP7              -> putWord8 0xb6
+        OP_NOP8              -> putWord8 0xb7
+        OP_NOP9              -> putWord8 0xb8
+        OP_NOP10             -> putWord8 0xb9
+
+
+-- | Check whether opcode is only data.
+isPushOp :: ScriptOp -> Bool
+isPushOp op = case op of
+    OP_PUSHDATA _ _ -> True
+    OP_0            -> True
+    OP_1NEGATE      -> True
+    OP_1            -> True
+    OP_2            -> True
+    OP_3            -> True
+    OP_4            -> True
+    OP_5            -> True
+    OP_6            -> True
+    OP_7            -> True
+    OP_8            -> True
+    OP_9            -> True
+    OP_10           -> True
+    OP_11           -> True
+    OP_12           -> True
+    OP_13           -> True
+    OP_14           -> True
+    OP_15           -> True
+    OP_16           -> True
+    _               -> False
+
+-- | Optimally encode data using one of the 4 types of data pushing opcodes.
+opPushData :: ByteString -> ScriptOp
+opPushData bs
+    | len <= 0x4b       = OP_PUSHDATA bs OPCODE
+    | len <= 0xff       = OP_PUSHDATA bs OPDATA1
+    | len <= 0xffff     = OP_PUSHDATA bs OPDATA2
+    | len <= 0xffffffff = OP_PUSHDATA bs OPDATA4
+    | otherwise         = error "opPushData: payload size too big"
+  where
+    len = B.length bs
+
+-- | Transforms integers @[1 .. 16]@ to 'ScriptOp' @[OP_1 .. OP_16]@.
+intToScriptOp :: Int -> ScriptOp
+intToScriptOp i
+    | i `elem` [1 .. 16] = op
+    | otherwise = err
+  where
+    op = either (const err) id . S.decode . B.singleton . fromIntegral $ i + 0x50
+    err = error $ "intToScriptOp: Invalid integer " ++ show i
+
+-- | Decode 'ScriptOp' @[OP_1 .. OP_16]@ to integers @[1 .. 16]@. This functions
+-- fails for other values of 'ScriptOp'
+scriptOpToInt :: ScriptOp -> Either String Int
+scriptOpToInt s
+    | res `elem` [1..16] = return res
+    | otherwise          = Left $ "scriptOpToInt: invalid opcode " ++ show s
+  where
+    res = fromIntegral (B.head $ S.encode s) - 0x50
+
+-- | Data type describing standard transaction output scripts. Output scripts
+-- provide the conditions that must be fulfilled for someone to spend the funds
+-- in a transaction output.
+data ScriptOutput
+      -- | pay to public key
+    = PayPK { getOutputPubKey :: !PubKeyI }
+      -- | pay to public key hash
+    | PayPKHash { getOutputHash :: !Hash160 }
+      -- | multisig
+    | PayMulSig { getOutputMulSigKeys     :: ![PubKeyI]
+                , getOutputMulSigRequired :: !Int }
+      -- | pay to a script hash
+    | PayScriptHash { getOutputHash :: !Hash160 }
+      -- | pay to witness public key hash
+    | PayWitnessPKHash { getOutputHash :: !Hash160 }
+      -- | pay to witness script hash
+    | PayWitnessScriptHash { getScriptHash :: !Hash256 }
+      -- | provably unspendable data carrier
+    | DataCarrier { getOutputData :: !ByteString }
+    deriving (Eq, Show)
+
+instance FromJSON ScriptOutput where
+    parseJSON = withText "scriptoutput" $ \t -> either fail return $
+        maybeToEither "scriptoutput not hex" (decodeHex t) >>=
+        decodeOutputBS
+
+instance ToJSON ScriptOutput where
+    toJSON = String . encodeHex . encodeOutputBS
+
+instance NFData ScriptOutput where
+    rnf (PayPK k)                = rnf k
+    rnf (PayPKHash a)            = rnf a
+    rnf (PayMulSig k r)          = rnf k `seq` rnf r
+    rnf (PayScriptHash a)        = rnf a
+    rnf (PayWitnessPKHash a)     = rnf a
+    rnf (PayWitnessScriptHash h) = rnf h
+    rnf (DataCarrier a)          = rnf a
+
+-- | Returns True if the script is a pay to public key output.
+isPayPK :: ScriptOutput -> Bool
+isPayPK (PayPK _) = True
+isPayPK _         = False
+
+-- | Returns True if the script is a pay to public key hash output.
+isPayPKHash :: ScriptOutput -> Bool
+isPayPKHash (PayPKHash _) = True
+isPayPKHash _             = False
+
+-- | Returns True if the script is a multisig output.
+isPayMulSig :: ScriptOutput -> Bool
+isPayMulSig (PayMulSig _ _) = True
+isPayMulSig _               = False
+
+-- | Returns true if the script is a pay to script hash output.
+isPayScriptHash :: ScriptOutput -> Bool
+isPayScriptHash (PayScriptHash _) = True
+isPayScriptHash _                 = False
+
+-- | Returns true if the script is a pay to witness public key hash output.
+isPayWitnessPKHash :: ScriptOutput -> Bool
+isPayWitnessPKHash (PayWitnessPKHash _) = True
+isPayWitnessPKHash _                    = False
+
+isPayWitnessScriptHash :: ScriptOutput -> Bool
+isPayWitnessScriptHash (PayWitnessScriptHash _) = True
+isPayWitnessScriptHash _                        = False
+
+-- | Returns True if the script is an @OP_RETURN@ "datacarrier" output
+isDataCarrier :: ScriptOutput -> Bool
+isDataCarrier (DataCarrier _) = True
+isDataCarrier _               = False
+
+-- | Tries to decode a 'ScriptOutput' from a 'Script'. This can fail if the
+-- script is not recognized as any of the standard output types.
+decodeOutput :: Script -> Either String ScriptOutput
+decodeOutput s = case scriptOps s of
+    -- Pay to PubKey
+    [OP_PUSHDATA bs _, OP_CHECKSIG] -> PayPK <$> S.decode bs
+    -- Pay to PubKey Hash
+    [OP_DUP, OP_HASH160, OP_PUSHDATA bs _, OP_EQUALVERIFY, OP_CHECKSIG] ->
+        PayPKHash <$> S.decode bs
+    -- Pay to Script Hash
+    [OP_HASH160, OP_PUSHDATA bs _, OP_EQUAL] ->
+        PayScriptHash <$> S.decode  bs
+    -- Pay to Witness
+    [OP_0, OP_PUSHDATA bs OPCODE]
+      | B.length bs == 20 -> PayWitnessPKHash     <$> S.decode bs
+      | B.length bs == 32 -> PayWitnessScriptHash <$> S.decode bs
+    -- Provably unspendable data carrier output
+    [OP_RETURN, OP_PUSHDATA bs _] -> Right $ DataCarrier bs
+    -- Pay to MultiSig Keys
+    _ -> matchPayMulSig s
+
+-- | Similar to 'decodeOutput' but decodes from a 'ByteString'.
+decodeOutputBS :: ByteString -> Either String ScriptOutput
+decodeOutputBS = decodeOutput <=< S.decode
+
+-- | Computes a 'Script' from a standard 'ScriptOutput'.
+encodeOutput :: ScriptOutput -> Script
+encodeOutput s = Script $ case s of
+    -- Pay to PubKey
+    (PayPK k) -> [opPushData $ S.encode k, OP_CHECKSIG]
+    -- Pay to PubKey Hash Address
+    (PayPKHash h) ->
+        [ OP_DUP, OP_HASH160, opPushData $ S.encode h, OP_EQUALVERIFY, OP_CHECKSIG]
+    -- Pay to MultiSig Keys
+    (PayMulSig ps r)
+      | r <= length ps ->
+        let opM = intToScriptOp r
+            opN = intToScriptOp $ length ps
+            keys = map (opPushData . S.encode) ps
+            in opM : keys ++ [opN, OP_CHECKMULTISIG]
+      | otherwise -> error "encodeOutput: PayMulSig r must be <= than pkeys"
+    -- Pay to Script Hash Address
+    (PayScriptHash h) ->
+        [ OP_HASH160, opPushData $ S.encode h, OP_EQUAL]
+    -- Pay to Witness PubKey Hash Address
+    (PayWitnessPKHash h) ->
+        [ OP_0, opPushData $ S.encode h ]
+    (PayWitnessScriptHash h) ->
+        [ OP_0, opPushData $ S.encode h ]
+    -- Provably unspendable output
+    (DataCarrier d) -> [OP_RETURN, opPushData d]
+
+-- | Similar to 'encodeOutput' but encodes to a ByteString
+encodeOutputBS :: ScriptOutput -> ByteString
+encodeOutputBS = S.encode . encodeOutput
+
+-- | Match @[OP_N, PubKey1, ..., PubKeyM, OP_M, OP_CHECKMULTISIG]@
+matchPayMulSig :: Script -> Either String ScriptOutput
+matchPayMulSig (Script ops) = case splitAt (length ops - 2) ops of
+    (m:xs,[n,OP_CHECKMULTISIG]) -> do
+        (intM,intN) <- liftM2 (,) (scriptOpToInt m) (scriptOpToInt n)
+        if intM <= intN && length xs == intN
+            then liftM2 PayMulSig (go xs) (return intM)
+            else Left "matchPayMulSig: Invalid M or N parameters"
+    _ -> Left "matchPayMulSig: script did not match output template"
+  where
+    go (OP_PUSHDATA bs _:xs) = liftM2 (:) (S.decode bs) (go xs)
+    go []                    = return []
+    go  _                    = Left "matchPayMulSig: invalid multisig opcode"
diff --git a/src/Network/Haskoin/Script/SigHash.hs b/src/Network/Haskoin/Script/SigHash.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Script/SigHash.hs
@@ -0,0 +1,270 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE OverloadedStrings          #-}
+module Network.Haskoin.Script.SigHash
+( SigHash
+, SigHashFlag(..)
+, sigHashAll
+, sigHashNone
+, sigHashSingle
+, hasAnyoneCanPayFlag
+, hasForkIdFlag
+, setAnyoneCanPayFlag
+, setForkIdFlag
+, isSigHashAll
+, isSigHashNone
+, isSigHashSingle
+, isSigHashUnknown
+, sigHashAddForkId
+, sigHashGetForkId
+, sigHashAddNetworkId
+, txSigHash
+, txSigHashForkId
+, TxSignature(..)
+, encodeTxSig
+, decodeTxSig
+) where
+
+import           Control.DeepSeq                    (NFData, rnf)
+import           Control.Monad
+import qualified Data.Aeson                         as J
+import           Data.Bits
+import           Data.ByteString                    (ByteString)
+import qualified Data.ByteString                    as BS
+import           Data.Maybe
+import           Data.Scientific
+import           Data.Serialize
+import           Data.Serialize.Put                 (runPut)
+import           Data.Word
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Crypto.Signature
+import           Network.Haskoin.Network
+import           Network.Haskoin.Script.Common
+import           Network.Haskoin.Transaction.Common
+import           Network.Haskoin.Util
+
+data SigHashFlag
+    = SIGHASH_ALL
+    | SIGHASH_NONE
+    | SIGHASH_SINGLE
+    | SIGHASH_FORKID
+    | SIGHASH_ANYONECANPAY
+    deriving (Eq, Ord, Show)
+
+instance Enum SigHashFlag where
+    fromEnum SIGHASH_ALL          = 0x01
+    fromEnum SIGHASH_NONE         = 0x02
+    fromEnum SIGHASH_SINGLE       = 0x03
+    fromEnum SIGHASH_FORKID       = 0x40
+    fromEnum SIGHASH_ANYONECANPAY = 0x80
+    toEnum 0x01 = SIGHASH_ALL
+    toEnum 0x02 = SIGHASH_NONE
+    toEnum 0x03 = SIGHASH_SINGLE
+    toEnum 0x40 = SIGHASH_FORKID
+    toEnum 0x80 = SIGHASH_ANYONECANPAY
+    toEnum _    = error "Not a valid sighash flag"
+
+-- | Data type representing the different ways a transaction can be signed.
+-- When producing a signature, a hash of the transaction is used as the message
+-- to be signed. The 'SigHash' parameter controls which parts of the
+-- transaction are used or ignored to produce the transaction hash. The idea is
+-- that if some part of a transaction is not used to produce the transaction
+-- hash, then you can change that part of the transaction after producing a
+-- signature without invalidating that signature.
+--
+-- If the 'SIGHASH_ANYONECANPAY' flag is set (true), then only the current input
+-- is signed. Otherwise, all of the inputs of a transaction are signed. The
+-- default value for 'SIGHASH_ANYONECANPAY' is unset (false).
+newtype SigHash = SigHash Word32
+    deriving (Eq, Ord, Enum, Bits, Num, Real, Integral, NFData, Show, Read)
+
+instance J.FromJSON SigHash where
+    parseJSON =
+        J.withScientific "sighash" $
+        maybe mzero (return . SigHash) . toBoundedInteger
+
+instance J.ToJSON SigHash where
+    toJSON = J.Number . fromIntegral
+
+sigHashNone :: SigHash
+sigHashNone = fromIntegral $ fromEnum SIGHASH_NONE
+
+sigHashAll :: SigHash
+sigHashAll = fromIntegral $ fromEnum SIGHASH_ALL
+
+sigHashSingle :: SigHash
+sigHashSingle = fromIntegral $ fromEnum SIGHASH_SINGLE
+
+sigHashForkId :: SigHash
+sigHashForkId = fromIntegral $ fromEnum SIGHASH_FORKID
+
+sigHashAnyoneCanPay :: SigHash
+sigHashAnyoneCanPay = fromIntegral $ fromEnum SIGHASH_ANYONECANPAY
+
+setForkIdFlag :: SigHash -> SigHash
+setForkIdFlag = (.|. sigHashForkId)
+
+setAnyoneCanPayFlag :: SigHash -> SigHash
+setAnyoneCanPayFlag = (.|. sigHashAnyoneCanPay)
+
+hasForkIdFlag :: SigHash -> Bool
+hasForkIdFlag = (/= 0) . (.&. sigHashForkId)
+
+hasAnyoneCanPayFlag :: SigHash -> Bool
+hasAnyoneCanPayFlag = (/= 0) . (.&. sigHashAnyoneCanPay)
+
+-- | Returns True if the 'SigHash' has the value 'SIGHASH_ALL'.
+isSigHashAll :: SigHash -> Bool
+isSigHashAll = (== sigHashAll) . (.&. 0x1f)
+
+-- | Returns True if the 'SigHash' has the value 'SIGHASH_NONE'.
+isSigHashNone :: SigHash -> Bool
+isSigHashNone = (== sigHashNone) . (.&. 0x1f)
+
+-- | Returns True if the 'SigHash' has the value 'SIGHASH_SINGLE'.
+isSigHashSingle :: SigHash -> Bool
+isSigHashSingle = (== sigHashSingle) . (.&. 0x1f)
+
+-- | Returns True if the 'SigHash' has the value 'SIGHASH_UNKNOWN'.
+isSigHashUnknown :: SigHash -> Bool
+isSigHashUnknown =
+    (`notElem` [sigHashAll, sigHashNone, sigHashSingle]) . (.&. 0x1f)
+
+sigHashAddForkId :: SigHash -> Word32 -> SigHash
+sigHashAddForkId sh w = (fromIntegral w `shiftL` 8) .|. (sh .&. 0x000000ff)
+
+sigHashAddNetworkId :: Network -> SigHash -> SigHash
+sigHashAddNetworkId net =
+    (`sigHashAddForkId` fromMaybe 0 (getSigHashForkId net))
+
+sigHashGetForkId :: SigHash -> Word32
+sigHashGetForkId = fromIntegral . (`shiftR` 8)
+
+-- | Computes the hash that will be used for signing a transaction.
+txSigHash :: Network
+          -> Tx      -- ^ transaction to sign
+          -> Script  -- ^ csript from output being spent
+          -> Word64  -- ^ value of output being spent
+          -> Int     -- ^ index of input being signed
+          -> SigHash -- ^ what to sign
+          -> Hash256 -- ^ hash to be signed
+txSigHash net tx out v i sh
+    | hasForkIdFlag sh && isJust (getSigHashForkId net) =
+        txSigHashForkId net tx out v i sh
+    | otherwise = do
+        let newIn = buildInputs (txIn tx) fout i sh
+        -- When SigSingle and input index > outputs, then sign integer 1
+        fromMaybe one $ do
+            newOut <- buildOutputs (txOut tx) i sh
+            let newTx = Tx (txVersion tx) newIn newOut [] (txLockTime tx)
+            return $
+                doubleSHA256 $
+                runPut $ do
+                    put newTx
+                    putWord32le $ fromIntegral sh
+  where
+    fout = Script $ filter (/= OP_CODESEPARATOR) $ scriptOps out
+    one = "0100000000000000000000000000000000000000000000000000000000000000"
+
+-- | Build transaction inputs for computing sighashes.
+buildInputs :: [TxIn] -> Script -> Int -> SigHash -> [TxIn]
+buildInputs txins out i sh
+    | hasAnyoneCanPayFlag sh =
+        [ (txins !! i) { scriptInput = encode out } ]
+    | isSigHashAll sh || isSigHashUnknown sh = single
+    | otherwise = zipWith noSeq single [0 ..]
+  where
+    emptyIn = map (\ti -> ti { scriptInput = BS.empty }) txins
+    single =
+        updateIndex i emptyIn $ \ti -> ti { scriptInput = encode out }
+    noSeq ti j =
+        if i == j
+        then ti
+        else ti { txInSequence = 0 }
+
+-- | Build transaction outputs for computing sighashes.
+buildOutputs :: [TxOut] -> Int -> SigHash -> Maybe [TxOut]
+buildOutputs txos i sh
+    | isSigHashAll sh || isSigHashUnknown sh = return txos
+    | isSigHashNone sh = return []
+    | i >= length txos = Nothing
+    | otherwise = return $ buffer ++ [txos !! i]
+  where
+    buffer = replicate i $ TxOut maxBound BS.empty
+
+-- | Compute the hash that will be used for signing a transaction. This
+-- function is used when the 'SIGHASH_FORKID' flag is set.
+txSigHashForkId
+    :: Network
+    -> Tx      -- ^ transaction to sign
+    -> Script  -- ^ script from output being spent
+    -> Word64  -- ^ value of output being spent
+    -> Int     -- ^ index of input being signed
+    -> SigHash -- ^ what to sign
+    -> Hash256 -- ^ hash to be signed
+txSigHashForkId net tx out v i sh =
+    doubleSHA256 . runPut $ do
+        putWord32le $ txVersion tx
+        put hashPrevouts
+        put hashSequence
+        put $ prevOutput $ txIn tx !! i
+        putScript out
+        putWord64le v
+        putWord32le $ txInSequence $ txIn tx !! i
+        put hashOutputs
+        putWord32le $ txLockTime tx
+        putWord32le $ fromIntegral $ sigHashAddNetworkId net sh
+  where
+    hashPrevouts
+        | not $ hasAnyoneCanPayFlag sh =
+            doubleSHA256 $ runPut $ mapM_ (put . prevOutput) $ txIn tx
+        | otherwise = zeros
+    hashSequence
+        | not (hasAnyoneCanPayFlag sh) &&
+              not (isSigHashSingle sh) && not (isSigHashNone sh) =
+            doubleSHA256 $ runPut $ mapM_ (putWord32le . txInSequence) $ txIn tx
+        | otherwise = zeros
+    hashOutputs
+        | not (isSigHashSingle sh) && not (isSigHashNone sh) =
+            doubleSHA256 $ runPut $ mapM_ put $ txOut tx
+        | isSigHashSingle sh && i < length (txOut tx) =
+            doubleSHA256 $ encode $ txOut tx !! i
+        | otherwise = zeros
+    putScript s = do
+        let encodedScript = encode s
+        put $ VarInt $ fromIntegral $ BS.length encodedScript
+        putByteString encodedScript
+    zeros :: Hash256
+    zeros = "0000000000000000000000000000000000000000000000000000000000000000"
+
+-- | Data type representing a signature together with a 'SigHash'. The 'SigHash'
+-- is serialized as one byte at the end of an ECDSA 'Sig'. All signatures in
+-- transaction inputs are of type 'TxSignature'.
+data TxSignature
+    = TxSignature { txSignature        :: !Sig
+                  , txSignatureSigHash :: !SigHash
+                  }
+    | TxSignatureEmpty
+    deriving (Eq, Show)
+
+instance NFData TxSignature where
+    rnf (TxSignature s h) = s `seq` rnf h `seq` ()
+    rnf TxSignatureEmpty  = ()
+
+-- | Serialize a 'TxSignature'.
+encodeTxSig :: TxSignature -> ByteString
+encodeTxSig TxSignatureEmpty = error "Can not encode an empty signature"
+encodeTxSig (TxSignature sig sh) = runPut $ putSig sig >> putWord8 (fromIntegral sh)
+
+-- | Deserialize a 'TxSignature'.
+decodeTxSig :: Network -> ByteString -> Either String TxSignature
+decodeTxSig net bs =
+    case decodeStrictSig $ BS.init bs of
+        Just sig -> do
+            let sh = fromIntegral $ BS.last bs
+            when (isSigHashUnknown sh) $
+                Left "Non-canonical signature: unknown hashtype byte"
+            when (isNothing (getSigHashForkId net) && hasForkIdFlag sh) $
+                Left "Non-canonical signature: invalid network for forkId"
+            return $ TxSignature sig sh
+        Nothing -> Left "Non-canonical signature: could not parse signature"
diff --git a/src/Network/Haskoin/Script/Standard.hs b/src/Network/Haskoin/Script/Standard.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Script/Standard.hs
@@ -0,0 +1,231 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Script.Standard
+( ScriptInput(..)
+, SimpleInput(..)
+, RedeemScript
+, p2shAddr
+, p2wshAddr
+, outputAddress
+, inputAddress
+, encodeInput
+, encodeInputBS
+, decodeInput
+, decodeInputBS
+, addressToOutput
+, addressToScript
+, addressToScriptBS
+, scriptToAddress
+, scriptToAddressBS
+, sortMulSig
+, scriptOpToInt
+, isSpendPK
+, isSpendPKHash
+, isSpendMulSig
+, isScriptHashInput
+) where
+
+import           Control.Applicative            ((<|>))
+import           Control.DeepSeq                (NFData, rnf)
+import           Control.Monad                  (guard, (<=<))
+import           Data.ByteString                (ByteString)
+import           Data.Function                  (on)
+import           Data.List                      (sortBy)
+import           Data.Serialize                 (decode, encode)
+import           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Keys.Common
+import           Network.Haskoin.Script.Common
+import           Network.Haskoin.Script.SigHash
+import           Network.Haskoin.Util
+
+
+-- | Data type describing standard transaction input scripts. Input scripts
+-- provide the signing data required to unlock the coins of the output they are
+-- trying to spend, except in pay-to-witness-public-key-hash and
+-- pay-to-script-hash transactions.
+data SimpleInput
+      -- | spend pay-to-public-key output
+    = SpendPK     { getInputSig :: !TxSignature }
+      -- | spend pay-to-public-key-hash output
+    | SpendPKHash { getInputSig :: !TxSignature
+                  , getInputKey :: !PubKeyI
+                  }
+      -- | spend multisig output
+    | SpendMulSig { getInputMulSigKeys :: ![TxSignature] }
+    deriving (Eq, Show)
+
+instance NFData SimpleInput where
+    rnf (SpendPK i)       = rnf i
+    rnf (SpendPKHash i k) = rnf i `seq` rnf k
+    rnf (SpendMulSig k)   = rnf k
+
+-- | Returns true if the input script is spending from a pay-to-public-key
+-- output.
+isSpendPK :: ScriptInput -> Bool
+isSpendPK (RegularInput (SpendPK _)) = True
+isSpendPK _                          = False
+
+-- | Returns true if the input script is spending from a pay-to-public-key-hash
+-- output.
+isSpendPKHash :: ScriptInput -> Bool
+isSpendPKHash (RegularInput (SpendPKHash _ _)) = True
+isSpendPKHash _                                = False
+
+-- | Returns true if the input script is spending a multisig output.
+isSpendMulSig :: ScriptInput -> Bool
+isSpendMulSig (RegularInput (SpendMulSig _)) = True
+isSpendMulSig _                              = False
+
+-- | Returns true if the input script is spending a pay-to-script-hash output.
+isScriptHashInput :: ScriptInput -> Bool
+isScriptHashInput (ScriptHashInput _ _) = True
+isScriptHashInput _                     = False
+
+-- | A redeem script is the output script serialized into the spending input
+-- script. It must be included in inputs that spend pay-to-script-hash outputs.
+type RedeemScript = ScriptOutput
+
+data ScriptInput
+    = RegularInput    { getRegularInput     :: SimpleInput }
+    | ScriptHashInput { getScriptHashInput  :: SimpleInput
+                      , getScriptHashRedeem :: RedeemScript
+                      }
+    deriving (Eq, Show)
+
+instance NFData ScriptInput where
+    rnf (RegularInput i)      = rnf i
+    rnf (ScriptHashInput i o) = rnf i `seq` rnf o
+
+
+-- | Compute a pay-to-script-hash address for an output script.
+p2shAddr :: Network -> ScriptOutput -> Address
+p2shAddr net out = ScriptAddress (addressHash (encodeOutputBS out)) net
+
+-- | Compute a pay-to-witness-script-hash address for an output script. Only on
+-- SegWit networks.
+p2wshAddr :: Network -> ScriptOutput -> Maybe Address
+p2wshAddr net out = do
+    guard (getSegWit net)
+    return $ WitnessScriptAddress (sha256 (encodeOutputBS out)) net
+
+-- | Encode an output script from an address. Will fail if using a
+-- pay-to-witness address on a non-SegWit network.
+addressToOutput :: Address -> Maybe ScriptOutput
+addressToOutput (PubKeyAddress h _)        = Just (PayPKHash h)
+addressToOutput (ScriptAddress h _)        = Just (PayScriptHash h)
+addressToOutput (WitnessPubKeyAddress h n)
+    | getSegWit n = Just (PayWitnessPKHash h)
+    | otherwise = Nothing
+addressToOutput (WitnessScriptAddress h n)
+    | getSegWit n = Just (PayWitnessScriptHash h)
+    | otherwise = Nothing
+
+-- | Get output script AST for an 'Address'.
+addressToScript :: Address -> Maybe Script
+addressToScript a = encodeOutput <$> addressToOutput a
+
+-- | Encode address as output script in 'ByteString' form.
+addressToScriptBS :: Address -> Maybe ByteString
+addressToScriptBS a = encode <$> addressToScript a
+
+-- | Decode an output script into an 'Address' if it has such representation.
+scriptToAddress :: Network -> Script -> Maybe Address
+scriptToAddress net = eitherToMaybe . (outputAddress net <=< decodeOutput)
+
+-- | Decode a serialized script into an 'Address'.
+scriptToAddressBS :: Network -> ByteString -> Maybe Address
+scriptToAddressBS net = eitherToMaybe . (outputAddress net <=< decodeOutputBS)
+
+-- | Get the 'Address' of a 'ScriptOutput'.
+outputAddress :: Network -> ScriptOutput -> Either String Address
+outputAddress net s =
+    case s of
+        PayPKHash h -> return $ PubKeyAddress h net
+        PayScriptHash h -> return $ ScriptAddress h net
+        PayPK k -> return $ pubKeyAddr net k
+        PayWitnessPKHash h
+            | getSegWit net -> return $ WitnessPubKeyAddress h net
+        PayWitnessScriptHash h
+            | getSegWit net -> return $ WitnessScriptAddress h net
+        _ -> Left "outputAddress: bad output script type"
+
+-- | Infer the address of a 'ScriptInput'
+inputAddress :: Network -> ScriptInput -> Either String Address
+inputAddress net s = case s of
+    RegularInput (SpendPKHash _ key) -> return $ pubKeyAddr net key
+    ScriptHashInput _ rdm -> return $ p2shAddr net rdm
+    _ -> Left "inputAddress: bad input script type"
+
+-- | Heuristic to decode an input script into one of the standard types.
+decodeSimpleInput :: Network -> Script -> Either String SimpleInput
+decodeSimpleInput net (Script ops) =
+    maybeToEither errMsg $ matchPK ops <|> matchPKHash ops <|> matchMulSig ops
+  where
+    matchPK [op] = SpendPK <$> f op
+    matchPK _    = Nothing
+    matchPKHash [op, OP_PUSHDATA pub _] =
+        SpendPKHash <$> f op <*> eitherToMaybe (decode pub)
+    matchPKHash _ = Nothing
+    matchMulSig (x:xs) = do
+        guard $ x == OP_0
+        SpendMulSig <$> mapM f xs
+    matchMulSig _ = Nothing
+    f OP_0                    = return TxSignatureEmpty
+    f (OP_PUSHDATA "" OPCODE) = f OP_0
+    f (OP_PUSHDATA bs _)      = eitherToMaybe $ decodeTxSig net bs
+    f _                       = Nothing
+    errMsg = "decodeInput: Could not decode script input"
+
+-- | Heuristic to decode a 'ScriptInput' from a 'Script'. This function fails if
+-- the script can not be parsed as a standard script input.
+decodeInput :: Network -> Script -> Either String ScriptInput
+decodeInput net s@(Script ops) =
+    maybeToEither errMsg $ matchSimpleInput <|> matchPayScriptHash
+  where
+    matchSimpleInput =
+        RegularInput <$> eitherToMaybe (decodeSimpleInput net s)
+    matchPayScriptHash =
+        case splitAt (length (scriptOps s) - 1) ops of
+            (is, [OP_PUSHDATA bs _]) -> do
+                rdm <- eitherToMaybe $ decodeOutputBS bs
+                inp <- eitherToMaybe $ decodeSimpleInput net $ Script is
+                return $ ScriptHashInput inp rdm
+            _ -> Nothing
+    errMsg = "decodeInput: Could not decode script input"
+
+-- | Like 'decodeInput' but decodes directly from a serialized script
+-- 'ByteString'.
+decodeInputBS :: Network -> ByteString -> Either String ScriptInput
+decodeInputBS net = decodeInput net <=< decode
+
+-- | Encode a standard input into a script.
+encodeInput :: ScriptInput -> Script
+encodeInput s = case s of
+    RegularInput ri -> encodeSimpleInput ri
+    ScriptHashInput i o -> Script $
+        scriptOps (encodeSimpleInput i) ++ [opPushData $ encodeOutputBS o]
+
+-- | Similar to 'encodeInput' but encodes directly to a serialized script
+-- 'ByteString'.
+encodeInputBS :: ScriptInput -> ByteString
+encodeInputBS = encode . encodeInput
+
+-- | Encode a standard 'SimpleInput' into opcodes as an input 'Script'.
+encodeSimpleInput :: SimpleInput -> Script
+encodeSimpleInput s =
+    Script $
+    case s of
+        SpendPK ts       -> [f ts]
+        SpendPKHash ts p -> [f ts, opPushData $ encode p]
+        SpendMulSig xs   -> OP_0 : map f xs
+  where
+    f TxSignatureEmpty = OP_0
+    f ts               = opPushData $ encodeTxSig ts
+
+-- | Sort the public keys of a multisig output in ascending order by comparing
+-- their compressed serialized representations. Refer to BIP-67.
+sortMulSig :: ScriptOutput -> ScriptOutput
+sortMulSig out = case out of
+    PayMulSig keys r -> PayMulSig (sortBy (compare `on` encode) keys) r
+    _ -> error "Can only call orderMulSig on PayMulSig scripts"
diff --git a/src/Network/Haskoin/Test.hs b/src/Network/Haskoin/Test.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Test.hs
@@ -0,0 +1,16 @@
+{-|
+  This package provides test types for Network.Haskoin
+-}
+module Network.Haskoin.Test
+    ( module X
+    ) where
+
+import           Network.Haskoin.Test.Address     as X
+import           Network.Haskoin.Test.Block       as X
+import           Network.Haskoin.Test.Crypto      as X
+import           Network.Haskoin.Test.Keys        as X
+import           Network.Haskoin.Test.Message     as X
+import           Network.Haskoin.Test.Network     as X
+import           Network.Haskoin.Test.Script      as X
+import           Network.Haskoin.Test.Transaction as X
+import           Network.Haskoin.Test.Util        as X
diff --git a/src/Network/Haskoin/Test/Address.hs b/src/Network/Haskoin/Test/Address.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Test/Address.hs
@@ -0,0 +1,22 @@
+{-|
+  Arbitrary types for Network.Haskoin.Crypto
+-}
+module Network.Haskoin.Test.Address where
+
+import           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Test.Crypto
+import           Test.QuickCheck
+
+-- | Arbitrary pay-to-public-key-hash or pay-to-script-hash address.
+arbitraryAddress :: Network -> Gen Address
+arbitraryAddress net =
+    oneof [arbitraryPubKeyAddress net, arbitraryScriptAddress net]
+
+-- | Arbitrary pay-to-public-key-hash address.
+arbitraryPubKeyAddress :: Network -> Gen Address
+arbitraryPubKeyAddress net = PubKeyAddress <$> arbitraryHash160 <*> pure net
+
+-- | Arbitrary pay-to-script-hash address.
+arbitraryScriptAddress :: Network -> Gen Address
+arbitraryScriptAddress net = ScriptAddress <$> arbitraryHash160 <*> pure net
diff --git a/src/Network/Haskoin/Test/Block.hs b/src/Network/Haskoin/Test/Block.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Test/Block.hs
@@ -0,0 +1,64 @@
+{-|
+  Arbitrary types for Network.Haskoin.Block
+-}
+module Network.Haskoin.Test.Block where
+
+import           Network.Haskoin.Block.Merkle
+import           Network.Haskoin.Block.Common
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Test.Crypto
+import           Network.Haskoin.Test.Network
+import           Network.Haskoin.Test.Transaction
+import           Test.QuickCheck
+
+-- | Block full or arbitrary transactions.
+arbitraryBlock :: Network -> Gen Block
+arbitraryBlock net = do
+    h   <- arbitraryBlockHeader
+    c   <- choose (0,10)
+    txs <- vectorOf c (arbitraryTx net)
+    return $ Block h txs
+
+-- | Block header with random hash.
+arbitraryBlockHeader :: Gen BlockHeader
+arbitraryBlockHeader =
+    BlockHeader <$> arbitrary
+                      <*> arbitraryBlockHash
+                      <*> arbitraryHash256
+                      <*> arbitrary
+                      <*> arbitrary
+                      <*> arbitrary
+
+-- | Arbitrary block hash.
+arbitraryBlockHash :: Gen BlockHash
+arbitraryBlockHash = BlockHash <$> arbitraryHash256
+
+-- | Arbitrary 'GetBlocks' object with at least one block hash.
+arbitraryGetBlocks :: Gen GetBlocks
+arbitraryGetBlocks =
+    GetBlocks <$> arbitrary
+              <*> listOf1 arbitraryBlockHash
+              <*> arbitraryBlockHash
+
+-- | Arbitrary 'GetHeaders' object with at least one block header.
+arbitraryGetHeaders :: Gen GetHeaders
+arbitraryGetHeaders =
+    GetHeaders <$> arbitrary
+               <*> listOf1 arbitraryBlockHash
+               <*> arbitraryBlockHash
+
+-- | Arbitrary 'Headers' object with at least one block header.
+arbitraryHeaders :: Gen Headers
+arbitraryHeaders =
+    Headers <$> listOf1 ((,) <$> arbitraryBlockHeader <*> arbitraryVarInt)
+
+-- | Arbitrary 'MerkleBlock' with at least one hash.
+arbitraryMerkleBlock :: Gen MerkleBlock
+arbitraryMerkleBlock = do
+    bh     <- arbitraryBlockHeader
+    ntx    <- arbitrary
+    hashes <- listOf1 arbitraryHash256
+    c      <- choose (1,10)
+    flags  <- vectorOf (c*8) arbitrary
+    return $ MerkleBlock bh ntx hashes flags
+
diff --git a/src/Network/Haskoin/Test/Crypto.hs b/src/Network/Haskoin/Test/Crypto.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Test/Crypto.hs
@@ -0,0 +1,28 @@
+{-|
+  Arbitrary types for Network.Haskoin.Crypto
+-}
+module Network.Haskoin.Test.Crypto where
+
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Test.Util
+import           Test.QuickCheck
+
+-- | Arbitrary 160-bit hash.
+arbitraryHash160 :: Gen Hash160
+arbitraryHash160 =
+    ripemd160 <$> arbitraryBSn 20
+
+-- | Arbitrary 256-bit hash.
+arbitraryHash256 :: Gen Hash256
+arbitraryHash256 =
+    sha256 <$> arbitraryBSn 32
+
+-- | Arbitrary 512-bit hash.
+arbitraryHash512 :: Gen Hash512
+arbitraryHash512 =
+    sha512 <$> arbitraryBSn 64
+
+-- | Arbitrary 32-bit checksum.
+arbitraryCheckSum32 :: Gen CheckSum32
+arbitraryCheckSum32 =
+    checkSum32 <$> arbitraryBSn 4
diff --git a/src/Network/Haskoin/Test/Keys.hs b/src/Network/Haskoin/Test/Keys.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Test/Keys.hs
@@ -0,0 +1,83 @@
+{-|
+  Arbitrary types for Network.Haskoin.Crypto
+-}
+module Network.Haskoin.Test.Keys where
+
+import           Data.Bits                        (clearBit)
+import           Data.List                        (foldl')
+import           Data.Word                        (Word32)
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Crypto.Signature
+import           Network.Haskoin.Keys.Common
+import           Network.Haskoin.Keys.Extended
+import           Network.Haskoin.Test.Crypto
+import           Test.QuickCheck
+
+-- | Arbitrary private key with arbitrary compressed flag.
+arbitrarySecKeyI :: Gen SecKeyI
+arbitrarySecKeyI = wrapSecKey <$> arbitrary <*> arbitrary
+
+-- | Arbitrary keypair, both either compressed or not.
+arbitraryKeyPair :: Gen (SecKeyI, PubKeyI)
+arbitraryKeyPair = do
+    k <- arbitrarySecKeyI
+    return (k, derivePubKeyI k)
+
+-- | Arbitrary extended private key.
+arbitraryXPrvKey :: Network -> Gen XPrvKey
+arbitraryXPrvKey net =
+    XPrvKey <$> arbitrary
+            <*> arbitrary
+            <*> arbitrary
+            <*> arbitraryHash256
+            <*> arbitrary
+            <*> pure net
+
+-- | Arbitrary extended public key with its corresponding private key.
+arbitraryXPubKey :: Network -> Gen (XPrvKey, XPubKey)
+arbitraryXPubKey net = (\k -> (k, deriveXPubKey k)) <$> arbitraryXPrvKey net
+
+{- Custom derivations -}
+
+-- | Arbitrary derivation index with last bit unset.
+genIndex :: Gen Word32
+genIndex = (`clearBit` 31) <$> arbitrary
+
+-- | Arbitrary BIP-32 path index. Can be hardened or not.
+arbitraryBip32PathIndex :: Gen Bip32PathIndex
+arbitraryBip32PathIndex =
+    oneof [ Bip32SoftIndex <$> genIndex
+          , Bip32HardIndex <$> genIndex
+          ]
+
+-- | Arbitrary BIP-32 derivation path composed of only hardened derivations.
+arbitraryHardPath :: Gen HardPath
+arbitraryHardPath = foldl' (:|) Deriv <$> listOf genIndex
+
+-- | Arbitrary BIP-32 derivation path composed of only non-hardened derivations.
+arbitrarySoftPath :: Gen SoftPath
+arbitrarySoftPath = foldl' (:/) Deriv <$> listOf genIndex
+
+-- | Arbitrary derivation path composed of hardened and non-hardened derivations.
+arbitraryDerivPath :: Gen DerivPath
+arbitraryDerivPath = concatBip32Segments <$> listOf arbitraryBip32PathIndex
+
+-- | Arbitrary parsed derivation path. Can contain 'ParsedPrv', 'ParsedPub' or
+-- 'ParsedEmpty' elements.
+arbitraryParsedPath :: Gen ParsedPath
+arbitraryParsedPath =
+    oneof [ ParsedPrv <$> arbitraryDerivPath
+          , ParsedPub <$> arbitraryDerivPath
+          , ParsedEmpty <$> arbitraryDerivPath
+          ]
+
+-- | Arbitrary message hash, private key, nonce and corresponding signature. The
+-- signature is generated with a random message, random private key and a random
+-- nonce.
+arbitrarySignature :: Gen (Hash256, SecKey, Sig)
+arbitrarySignature = do
+    msg <- arbitraryHash256
+    key <- arbitrary
+    let sig = signHash key msg
+    return (msg, key, sig)
diff --git a/src/Network/Haskoin/Test/Message.hs b/src/Network/Haskoin/Test/Message.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Test/Message.hs
@@ -0,0 +1,47 @@
+{-|
+  Arbitrary types for Network.Haskoin.Node.Message
+-}
+module Network.Haskoin.Test.Message where
+
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Network.Message
+import           Network.Haskoin.Test.Block
+import           Network.Haskoin.Test.Crypto
+import           Network.Haskoin.Test.Network
+import           Network.Haskoin.Test.Transaction
+import           Test.QuickCheck
+
+-- | Arbitrary 'MessageHeader'.
+arbitraryMessageHeader :: Gen MessageHeader
+arbitraryMessageHeader =
+    MessageHeader <$> arbitrary
+                  <*> arbitraryMessageCommand
+                  <*> arbitrary
+                  <*> arbitraryCheckSum32
+
+-- | Arbitrary 'Message'.
+arbitraryMessage :: Network -> Gen Message
+arbitraryMessage net =
+    oneof
+        [ MVersion <$> arbitraryVersion
+        , return MVerAck
+        , MAddr <$> arbitraryAddr1
+        , MInv <$> arbitraryInv1
+        , MGetData <$> arbitraryGetData
+        , MNotFound <$> arbitraryNotFound
+        , MGetBlocks <$> arbitraryGetBlocks
+        , MGetHeaders <$> arbitraryGetHeaders
+        , MTx <$> arbitraryTx net
+        , MBlock <$> arbitraryBlock net
+        , MMerkleBlock <$> arbitraryMerkleBlock
+        , MHeaders <$> arbitraryHeaders
+        , return MGetAddr
+        , MFilterLoad <$> arbitraryFilterLoad
+        , MFilterAdd <$> arbitraryFilterAdd
+        , return MFilterClear
+        , MPing <$> arbitraryPing
+        , MPong <$> arbitraryPong
+        , MAlert <$> arbitraryAlert
+        , MReject <$> arbitraryReject
+        , return MSendHeaders
+        ]
diff --git a/src/Network/Haskoin/Test/Network.hs b/src/Network/Haskoin/Test/Network.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Test/Network.hs
@@ -0,0 +1,168 @@
+{-|
+  Arbitrary types for Network.Haskoin.Network
+-}
+module Network.Haskoin.Test.Network where
+
+import qualified Data.ByteString             as BS (empty, pack)
+import           Data.Word                   (Word16, Word32)
+import           Network.Haskoin.Network
+import           Network.Haskoin.Test.Crypto
+import           Network.Haskoin.Test.Util
+import           Network.Socket              (SockAddr (..))
+import           Test.QuickCheck
+
+-- | Arbitrary 'VarInt'.
+arbitraryVarInt :: Gen VarInt
+arbitraryVarInt = VarInt <$> arbitrary
+
+-- | Arbitrary 'VarString'.
+arbitraryVarString :: Gen VarString
+arbitraryVarString = VarString <$> arbitraryBS
+
+-- | Arbitrary 'NetworkAddress'.
+arbitraryNetworkAddress :: Gen NetworkAddress
+arbitraryNetworkAddress = do
+    s <- arbitrary
+    a <- arbitrary
+    p <- arbitrary
+    NetworkAddress s <$> oneof
+        [ do
+            b <- arbitrary
+            c <- arbitrary
+            d <- arbitrary
+            return $ SockAddrInet6 (fromIntegral p) 0 (a,b,c,d) 0
+        , return $ SockAddrInet (fromIntegral (p :: Word16)) a
+        ]
+
+-- | Arbitrary 'NetworkAddressTime'.
+arbitraryNetworkAddressTime :: Gen (Word32, NetworkAddress)
+arbitraryNetworkAddressTime = (,) <$> arbitrary <*> arbitraryNetworkAddress
+
+-- | Arbitrary 'InvType'.
+arbitraryInvType :: Gen InvType
+arbitraryInvType = elements [InvError, InvTx, InvBlock, InvMerkleBlock]
+
+-- | Arbitrary 'InvVector'.
+arbitraryInvVector :: Gen InvVector
+arbitraryInvVector = InvVector <$> arbitraryInvType <*> arbitraryHash256
+
+-- | Arbitrary non-empty 'Inv'.
+arbitraryInv1 :: Gen Inv
+arbitraryInv1 = Inv <$> listOf1 arbitraryInvVector
+
+-- | Arbitrary 'Version'.
+arbitraryVersion :: Gen Version
+arbitraryVersion =
+    Version <$> arbitrary
+            <*> arbitrary
+            <*> arbitrary
+            <*> arbitraryNetworkAddress
+            <*> arbitraryNetworkAddress
+            <*> arbitrary
+            <*> arbitraryVarString
+            <*> arbitrary
+            <*> arbitrary
+
+-- | Arbitrary non-empty 'Addr'.
+arbitraryAddr1 :: Gen Addr
+arbitraryAddr1 = Addr <$> listOf1 arbitraryNetworkAddressTime
+
+-- | Arbitrary 'Alert' with random payload and signature. Signature is not
+-- valid.
+arbitraryAlert :: Gen Alert
+arbitraryAlert = Alert <$> arbitraryVarString <*> arbitraryVarString
+
+-- | Arbitrary 'Reject'.
+arbitraryReject :: Gen Reject
+arbitraryReject = do
+    m <- arbitraryMessageCommand
+    c <- arbitraryRejectCode
+    s <- arbitraryVarString
+    d <- oneof [ return BS.empty
+               , BS.pack <$> vectorOf 32 arbitrary
+               ]
+    return $ Reject m c s d
+
+-- | Arbitrary 'RejectCode'.
+arbitraryRejectCode :: Gen RejectCode
+arbitraryRejectCode =
+    elements
+        [ RejectMalformed
+        , RejectInvalid
+        , RejectInvalid
+        , RejectDuplicate
+        , RejectNonStandard
+        , RejectDust
+        , RejectInsufficientFee
+        , RejectCheckpoint
+        ]
+
+-- | Arbitrary non-empty 'GetData'.
+arbitraryGetData :: Gen GetData
+arbitraryGetData = GetData <$> listOf1 arbitraryInvVector
+
+-- | Arbitrary 'NotFound'.
+arbitraryNotFound :: Gen NotFound
+arbitraryNotFound = NotFound <$> listOf1 arbitraryInvVector
+
+-- | Arbitrary 'Ping'.
+arbitraryPing :: Gen Ping
+arbitraryPing = Ping <$> arbitrary
+
+-- | Arbitrary 'Pong'.
+arbitraryPong :: Gen Pong
+arbitraryPong = Pong <$> arbitrary
+
+-- | Arbitrary bloom filter flags.
+arbitraryBloomFlags :: Gen BloomFlags
+arbitraryBloomFlags =
+    elements
+        [ BloomUpdateNone
+        , BloomUpdateAll
+        , BloomUpdateP2PubKeyOnly
+        ]
+
+-- | Arbitrary bloom filter with its corresponding number of elements
+-- and false positive rate.
+arbitraryBloomFilter :: Gen (Int, Double, BloomFilter)
+arbitraryBloomFilter = do
+    n     <- choose (0,100000)
+    fp    <- choose (1e-8,1)
+    tweak <- arbitrary
+    fl    <- arbitraryBloomFlags
+    return (n, fp, bloomCreate n fp tweak fl)
+
+-- | Arbitrary 'FilterLoad'.
+arbitraryFilterLoad :: Gen FilterLoad
+arbitraryFilterLoad = do
+    (_, _, bf) <- arbitraryBloomFilter
+    return $ FilterLoad bf
+
+-- | Arbitrary 'FilterAdd'.
+arbitraryFilterAdd :: Gen FilterAdd
+arbitraryFilterAdd = FilterAdd <$> arbitraryBS
+
+-- | Arbitrary 'MessageCommand'.
+arbitraryMessageCommand :: Gen MessageCommand
+arbitraryMessageCommand =
+    elements
+        [ MCVersion
+        , MCVerAck
+        , MCAddr
+        , MCInv
+        , MCGetData
+        , MCNotFound
+        , MCGetBlocks
+        , MCGetHeaders
+        , MCTx
+        , MCBlock
+        , MCMerkleBlock
+        , MCHeaders
+        , MCGetAddr
+        , MCFilterLoad
+        , MCFilterAdd
+        , MCFilterClear
+        , MCPing
+        , MCPong
+        , MCAlert
+        ]
diff --git a/src/Network/Haskoin/Test/Script.hs b/src/Network/Haskoin/Test/Script.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Test/Script.hs
@@ -0,0 +1,360 @@
+{-|
+  Arbitrary types for Network.Haskoin.Script
+-}
+module Network.Haskoin.Test.Script where
+
+import           Data.Maybe
+import           Data.Word
+import           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Keys.Common
+import           Network.Haskoin.Script
+import           Network.Haskoin.Test.Address
+import           Network.Haskoin.Test.Crypto
+import           Network.Haskoin.Test.Keys
+import           Network.Haskoin.Test.Util
+import           Network.Haskoin.Transaction.Common
+import           Network.Haskoin.Util
+import           Test.QuickCheck
+
+-- | Arbitrary 'Script' with random script ops.
+arbitraryScript :: Gen Script
+arbitraryScript = Script <$> listOf arbitraryScriptOp
+
+-- | Arbitrary 'ScriptOp' (push operations have random data).
+arbitraryScriptOp :: Gen ScriptOp
+arbitraryScriptOp =
+    oneof
+          -- Pushing Data
+        [ opPushData <$> arbitraryBS1
+        , return OP_0
+        , return OP_1NEGATE
+        , return OP_RESERVED
+        , return OP_1
+        , return OP_2
+        , return OP_3
+        , return OP_4
+        , return OP_5
+        , return OP_6
+        , return OP_7
+        , return OP_8
+        , return OP_9
+        , return OP_10
+        , return OP_11
+        , return OP_12
+        , return OP_13
+        , return OP_14
+        , return OP_15
+        , return OP_16
+        -- Flow control
+        , return OP_NOP
+        , return OP_VER
+        , return OP_IF
+        , return OP_NOTIF
+        , return OP_VERIF
+        , return OP_VERNOTIF
+        , return OP_ELSE
+        , return OP_ENDIF
+        , return OP_VERIFY
+        , return OP_RETURN
+        -- Stack operations
+        , return OP_TOALTSTACK
+        , return OP_FROMALTSTACK
+        , return OP_IFDUP
+        , return OP_DEPTH
+        , return OP_DROP
+        , return OP_DUP
+        , return OP_NIP
+        , return OP_OVER
+        , return OP_PICK
+        , return OP_ROLL
+        , return OP_ROT
+        , return OP_SWAP
+        , return OP_TUCK
+        , return OP_2DROP
+        , return OP_2DUP
+        , return OP_3DUP
+        , return OP_2OVER
+        , return OP_2ROT
+        , return OP_2SWAP
+        -- Splice
+        , return OP_CAT
+        , return OP_SUBSTR
+        , return OP_LEFT
+        , return OP_RIGHT
+        , return OP_SIZE
+        -- Bitwise logic
+        , return OP_INVERT
+        , return OP_AND
+        , return OP_OR
+        , return OP_XOR
+        , return OP_EQUAL
+        , return OP_EQUALVERIFY
+        , return OP_RESERVED1
+        , return OP_RESERVED2
+        -- Arithmetic
+        , return OP_1ADD
+        , return OP_1SUB
+        , return OP_2MUL
+        , return OP_2DIV
+        , return OP_NEGATE
+        , return OP_ABS
+        , return OP_NOT
+        , return OP_0NOTEQUAL
+        , return OP_ADD
+        , return OP_SUB
+        , return OP_MUL
+        , return OP_DIV
+        , return OP_MOD
+        , return OP_LSHIFT
+        , return OP_RSHIFT
+        , return OP_BOOLAND
+        , return OP_BOOLOR
+        , return OP_NUMEQUAL
+        , return OP_NUMEQUALVERIFY
+        , return OP_NUMNOTEQUAL
+        , return OP_LESSTHAN
+        , return OP_GREATERTHAN
+        , return OP_LESSTHANOREQUAL
+        , return OP_GREATERTHANOREQUAL
+        , return OP_MIN
+        , return OP_MAX
+        , return OP_WITHIN
+        -- Crypto
+        , return OP_RIPEMD160
+        , return OP_SHA1
+        , return OP_SHA256
+        , return OP_HASH160
+        , return OP_HASH256
+        , return OP_CODESEPARATOR
+        , return OP_CHECKSIG
+        , return OP_CHECKSIGVERIFY
+        , return OP_CHECKMULTISIG
+        , return OP_CHECKMULTISIGVERIFY
+        -- Expansion
+        , return OP_NOP1
+        , return OP_NOP2
+        , return OP_NOP3
+        , return OP_NOP4
+        , return OP_NOP5
+        , return OP_NOP6
+        , return OP_NOP7
+        , return OP_NOP8
+        , return OP_NOP9
+        , return OP_NOP10
+        -- Other
+        , return OP_PUBKEYHASH
+        , return OP_PUBKEY
+        , return $ OP_INVALIDOPCODE 0xff
+        ]
+
+-- | Arbtirary 'ScriptOp' with a value in @[OP_1 .. OP_16]@.
+arbitraryIntScriptOp :: Gen ScriptOp
+arbitraryIntScriptOp =
+    elements
+        [ OP_1,  OP_2,  OP_3,  OP_4
+        , OP_5,  OP_6,  OP_7,  OP_8
+        , OP_9,  OP_10, OP_11, OP_12
+        , OP_13, OP_14, OP_15, OP_16
+        ]
+
+-- | Arbitrary 'PushDataType'.
+arbitraryPushDataType :: Gen PushDataType
+arbitraryPushDataType = elements [OPCODE, OPDATA1, OPDATA2, OPDATA4]
+
+-- | Arbitrary 'SigHash' (including invalid/unknown sighash codes).
+arbitrarySigHash :: Gen SigHash
+arbitrarySigHash = fromIntegral <$> (arbitrary :: Gen Word32)
+
+-- | Arbitrary valid 'SigHash'.
+arbitraryValidSigHash :: Network -> Gen SigHash
+arbitraryValidSigHash net = do
+    sh <- elements [sigHashAll, sigHashNone, sigHashSingle]
+    f1 <-
+        elements $
+        if isJust (getSigHashForkId net)
+            then [id, setForkIdFlag]
+            else [id]
+    f2 <- elements [id, setAnyoneCanPayFlag]
+    return $ f1 $ f2 sh
+
+-- | Arbitrary message hash, private key and corresponding 'TxSignature'. The
+-- signature is generated deterministically using a random message and a random
+-- private key.
+arbitraryTxSignature :: Network -> Gen (TxHash, SecKey, TxSignature)
+arbitraryTxSignature net = do
+    (msg, key, sig) <- arbitrarySignature
+    sh <- (fromIntegral <$> (arbitrary :: Gen Word8)) `suchThat` filterBad
+    let txsig = TxSignature sig sh
+    return (TxHash msg, key, txsig)
+  where
+    filterBad sh = not $
+        isSigHashUnknown sh ||
+        isNothing (getSigHashForkId net) && hasForkIdFlag sh
+
+-- | Arbitrary transaction signature that could also be empty.
+arbitraryTxSignatureEmpty :: Network -> Gen TxSignature
+arbitraryTxSignatureEmpty net =
+    frequency [ (1, return TxSignatureEmpty)
+              , (10, lst3 <$> arbitraryTxSignature net)
+              ]
+
+-- | Arbitrary m of n parameters.
+arbitraryMSParam :: Gen (Int, Int)
+arbitraryMSParam = do
+    m <- choose (1,16)
+    n <- choose (m,16)
+    return (m, n)
+
+-- | Arbitrary 'ScriptOutput' (Can by any valid type).
+arbitraryScriptOutput :: Network -> Gen ScriptOutput
+arbitraryScriptOutput net =
+    oneof $
+    [ arbitraryPKOutput
+    , arbitraryPKHashOutput
+    , arbitraryMSOutput
+    , arbitrarySHOutput net
+    , arbitraryDCOutput
+    ] ++
+    if getSegWit net
+        then [arbitraryWPKHashOutput, arbitraryWSHOutput]
+        else []
+
+-- | Arbitrary 'ScriptOutput' of type 'PayPK', 'PayPKHash' or 'PayMS'
+-- (Not 'PayScriptHash', 'DataCarrier', or SegWit)
+arbitrarySimpleOutput ::Gen ScriptOutput
+arbitrarySimpleOutput =
+    oneof
+        [ arbitraryPKOutput
+        , arbitraryPKHashOutput
+        , arbitraryMSOutput
+        ]
+
+-- | Arbitrary 'ScriptOutput' of type 'PayPK'
+arbitraryPKOutput :: Gen ScriptOutput
+arbitraryPKOutput =  PayPK . snd <$> arbitraryKeyPair
+
+-- | Arbitrary 'ScriptOutput' of type 'PayPKHash'
+arbitraryPKHashOutput :: Gen ScriptOutput
+arbitraryPKHashOutput = PayPKHash <$> arbitraryHash160
+
+-- | Arbitrary 'PayWitnessPKHash' output.
+arbitraryWPKHashOutput :: Gen ScriptOutput
+arbitraryWPKHashOutput = PayWitnessPKHash <$> arbitraryHash160
+
+-- | Arbitrary 'PayWitnessScriptHash' output.
+arbitraryWSHOutput :: Gen ScriptOutput
+arbitraryWSHOutput = PayWitnessScriptHash <$> arbitraryHash256
+
+-- | Arbitrary 'ScriptOutput' of type 'PayMS'.
+arbitraryMSOutput :: Gen ScriptOutput
+arbitraryMSOutput = do
+    (m, n) <- arbitraryMSParam
+    keys <- map snd <$> vectorOf n arbitraryKeyPair
+    return $ PayMulSig keys m
+
+-- | Arbitrary 'ScriptOutput' of type 'PayMS', only using compressed keys.
+arbitraryMSOutputC :: Gen ScriptOutput
+arbitraryMSOutputC = do
+    (m, n) <- arbitraryMSParam
+    keys <-
+        map snd <$>
+        vectorOf n (arbitraryKeyPair `suchThat` (pubKeyCompressed . snd))
+    return $ PayMulSig keys m
+
+-- | Arbitrary 'ScriptOutput' of type 'PayScriptHash'.
+arbitrarySHOutput :: Network -> Gen ScriptOutput
+arbitrarySHOutput net =
+    PayScriptHash . getAddrHash160 <$> arbitraryScriptAddress net
+
+-- | Arbitrary 'ScriptOutput' of type 'DataCarrier'.
+arbitraryDCOutput :: Gen ScriptOutput
+arbitraryDCOutput = DataCarrier <$> arbitraryBS1
+
+-- | Arbitrary 'ScriptInput'.
+arbitraryScriptInput :: Network -> Gen ScriptInput
+arbitraryScriptInput net =
+    oneof
+        [ arbitraryPKInput net
+        , arbitraryPKHashInput net
+        , arbitraryMSInput net
+        , arbitrarySHInput net
+        ]
+
+-- | Arbitrary 'ScriptInput' of type 'SpendPK', 'SpendPKHash' or 'SpendMulSig'
+-- (not 'ScriptHashInput')
+arbitrarySimpleInput :: Network -> Gen ScriptInput
+arbitrarySimpleInput net =
+    oneof
+        [ arbitraryPKInput net
+        , arbitraryPKHashInput net
+        , arbitraryMSInput net
+        ]
+
+-- | Arbitrary 'ScriptInput' of type 'SpendPK'.
+arbitraryPKInput :: Network -> Gen ScriptInput
+arbitraryPKInput net = RegularInput . SpendPK <$> arbitraryTxSignatureEmpty net
+
+-- | Arbitrary 'ScriptInput' of type 'SpendPK'.
+arbitraryPKHashInput :: Network -> Gen ScriptInput
+arbitraryPKHashInput net = do
+    sig <- arbitraryTxSignatureEmpty net
+    key <- snd <$> arbitraryKeyPair
+    return $ RegularInput $ SpendPKHash sig key
+
+-- | Like 'arbitraryPKHashInput' without empty signatures.
+arbitraryPKHashInputFull :: Network -> Gen ScriptInput
+arbitraryPKHashInputFull net = do
+    sig <- lst3 <$> arbitraryTxSignature net
+    key <- snd <$> arbitraryKeyPair
+    return $ RegularInput $ SpendPKHash sig key
+
+-- | Like above but only compressed.
+arbitraryPKHashInputFullC :: Network -> Gen ScriptInput
+arbitraryPKHashInputFullC net = do
+    sig <- lst3 <$> arbitraryTxSignature net
+    key <- fmap snd $ arbitraryKeyPair `suchThat` (pubKeyCompressed . snd)
+    return $ RegularInput $ SpendPKHash sig key
+
+-- | Arbitrary 'ScriptInput' of type 'SpendMulSig'.
+arbitraryMSInput :: Network -> Gen ScriptInput
+arbitraryMSInput net = do
+    m    <- fst <$> arbitraryMSParam
+    sigs <- vectorOf m (arbitraryTxSignatureEmpty net)
+    return $ RegularInput $ SpendMulSig sigs
+
+-- | Arbitrary 'ScriptInput' of type 'ScriptHashInput'.
+arbitrarySHInput :: Network -> Gen ScriptInput
+arbitrarySHInput net = do
+    i <- arbitrarySimpleInput net
+    ScriptHashInput (getRegularInput i) <$> arbitrarySimpleOutput
+
+-- | Arbitrary 'ScriptInput' of type 'ScriptHashInput' containing a
+-- 'RedeemScript' of type 'PayMulSig' and an input of type 'SpendMulSig'.
+arbitraryMulSigSHInput :: Network -> Gen ScriptInput
+arbitraryMulSigSHInput net = do
+    rdm@(PayMulSig _ m) <- arbitraryMSOutput
+    sigs <- vectorOf m (arbitraryTxSignatureEmpty net)
+    return $ ScriptHashInput (SpendMulSig sigs) rdm
+
+-- | Arbitrary 'ScriptInput' of type 'ScriptHashInput' containing a
+-- 'RedeemScript' of type 'PayMulSig' and an input of type 'SpendMulSig'.
+arbitraryMulSigSHInputC :: Network -> Gen ScriptInput
+arbitraryMulSigSHInputC net = do
+    rdm@(PayMulSig _ m) <- arbitraryMSOutputC
+    sigs <- vectorOf m (arbitraryTxSignatureEmpty net)
+    return $ ScriptHashInput (SpendMulSig sigs) rdm
+
+-- | Like 'arbitraryMulSigSHCInput' with no empty signatures.
+arbitraryMulSigSHInputFull :: Network -> Gen ScriptInput
+arbitraryMulSigSHInputFull net = do
+    rdm@(PayMulSig _ m) <- arbitraryMSOutput
+    sigs <- map lst3 <$> vectorOf m (arbitraryTxSignature net)
+    return $ ScriptHashInput (SpendMulSig sigs) rdm
+
+-- | Like 'arbitraryMulSigSHCInput' with no empty signatures.
+arbitraryMulSigSHInputFullC :: Network -> Gen ScriptInput
+arbitraryMulSigSHInputFullC net = do
+    rdm@(PayMulSig _ m) <- arbitraryMSOutputC
+    sigs <- map lst3 <$> vectorOf m (arbitraryTxSignature net)
+    return $ ScriptHashInput (SpendMulSig sigs) rdm
diff --git a/src/Network/Haskoin/Test/Transaction.hs b/src/Network/Haskoin/Test/Transaction.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Test/Transaction.hs
@@ -0,0 +1,245 @@
+{-|
+  Arbitrary types for Network.Haskoin.Transaction.
+-}
+module Network.Haskoin.Test.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           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Keys.Common
+import           Network.Haskoin.Script
+import           Network.Haskoin.Test.Crypto
+import           Network.Haskoin.Test.Keys
+import           Network.Haskoin.Test.Script
+import           Network.Haskoin.Test.Util
+import           Network.Haskoin.Transaction
+import           Test.QuickCheck
+
+newtype TestCoin = TestCoin { getTestCoin :: Word64 }
+    deriving (Eq, Show)
+
+instance Coin TestCoin where
+    coinValue = getTestCoin
+
+-- | Arbitrary transaction hash (for non-existent transaction).
+arbitraryTxHash :: Gen TxHash
+arbitraryTxHash = TxHash <$> arbitraryHash256
+
+-- | Arbitrary amount of Satoshi as 'Word64' (Between 1 and 21e14)
+arbitrarySatoshi :: Network -> Gen TestCoin
+arbitrarySatoshi net = TestCoin <$> choose (1, getMaxSatoshi net)
+
+-- | Arbitrary 'OutPoint'.
+arbitraryOutPoint :: Gen OutPoint
+arbitraryOutPoint = OutPoint <$> arbitraryTxHash <*> arbitrary
+
+-- | Arbitrary 'TxOut'.
+arbitraryTxOut :: Network -> Gen TxOut
+arbitraryTxOut net =
+    TxOut <$> (getTestCoin <$> arbitrarySatoshi net)
+          <*> (encodeOutputBS <$> arbitraryScriptOutput net)
+
+-- | Arbitrary 'TxIn'.
+arbitraryTxIn :: Network -> Gen TxIn
+arbitraryTxIn net =
+    TxIn <$> arbitraryOutPoint
+         <*> (encodeInputBS <$> arbitraryScriptInput net)
+         <*> arbitrary
+
+-- | Arbitrary transaction. Can be regular or with witnesses.
+arbitraryTx :: Network -> Gen Tx
+arbitraryTx net = oneof [arbitraryLegacyTx net, arbitraryWitnessTx net]
+
+-- | Arbitrary regular transaction.
+arbitraryLegacyTx :: Network -> Gen Tx
+arbitraryLegacyTx net = arbitraryWLTx net False
+
+-- | Arbitrary witness transaction (witness data is fake).
+arbitraryWitnessTx :: Network -> Gen Tx
+arbitraryWitnessTx net = arbitraryWLTx net True
+
+arbitraryWLTx :: Network -> Bool -> Gen Tx
+arbitraryWLTx net wit = do
+    ni <- choose (0, 5)
+    no <-
+        if wit
+            then choose (0, 5)
+            else choose
+                     ( if ni == 0
+                           then 2
+                           else 0
+                     , 5 -- avoid witness case
+                      )
+    inps <- vectorOf ni (arbitraryTxIn net)
+    outs <- vectorOf no (arbitraryTxOut net)
+    let uniqueInps = nubBy (\a b -> prevOutput a == prevOutput b) inps
+    w <- if wit then vectorOf (length uniqueInps) (listOf arbitraryBS) else return []
+    Tx <$> arbitrary <*> pure uniqueInps <*> pure outs <*> pure w <*> 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 -> Gen Tx
+arbitraryAddrOnlyTx net = do
+    ni <- choose (0, 5)
+    no <- choose (0, 5)
+    inps <- vectorOf ni (arbitraryAddrOnlyTxIn net)
+    outs <- vectorOf no (arbitraryAddrOnlyTxOut net)
+    Tx <$> arbitrary <*> pure inps <*> pure outs <*> pure [] <*> arbitrary
+
+-- | Like 'arbitraryAddrOnlyTx' without empty signatures in the inputs.
+arbitraryAddrOnlyTxFull :: Network -> Gen Tx
+arbitraryAddrOnlyTxFull net = do
+    ni <- choose (0, 5)
+    no <- choose (0, 5)
+    inps <- vectorOf ni (arbitraryAddrOnlyTxInFull net)
+    outs <- vectorOf no (arbitraryAddrOnlyTxOut net)
+    Tx <$> arbitrary <*> pure inps <*> pure outs <*> pure [] <*> arbitrary
+
+-- | Arbitrary TxIn that can only be of type 'SpendPKHash' or 'SpendScriptHash'
+-- (multisig). Only compressed public keys are used.
+arbitraryAddrOnlyTxIn :: Network -> Gen TxIn
+arbitraryAddrOnlyTxIn net = do
+    inp <- oneof [arbitraryPKHashInput net, arbitraryMulSigSHInput net]
+    TxIn <$> arbitraryOutPoint <*> pure (encodeInputBS inp) <*> arbitrary
+
+-- | like 'arbitraryAddrOnlyTxIn' with no empty signatures.
+arbitraryAddrOnlyTxInFull :: Network -> Gen TxIn
+arbitraryAddrOnlyTxInFull net = do
+    inp <-
+        oneof [arbitraryPKHashInputFullC net, arbitraryMulSigSHInputFullC net]
+    TxIn <$> arbitraryOutPoint <*> pure (encodeInputBS inp) <*> arbitrary
+
+-- | Arbitrary 'TxOut' that can only be of type 'PayPKHash' or 'PaySH'.
+arbitraryAddrOnlyTxOut :: Network -> Gen TxOut
+arbitraryAddrOnlyTxOut net = do
+    v <- getTestCoin <$> arbitrarySatoshi net
+    out <- oneof [ arbitraryPKHashOutput, arbitrarySHOutput net ]
+    return $ TxOut v $ encodeOutputBS out
+
+-- | Arbitrary 'SigInput' with the corresponding private keys used
+-- to generate the 'ScriptOutput' or 'RedeemScript'.
+arbitrarySigInput :: Network -> Gen (SigInput, [SecKeyI])
+arbitrarySigInput net =
+    oneof
+        [ arbitraryPKSigInput net >>= \(si, k) -> return (si, [k])
+        , arbitraryPKHashSigInput  net >>= \(si, k) -> return (si, [k])
+        , arbitraryMSSigInput net
+        , arbitrarySHSigInput net
+        ]
+
+-- | Arbitrary 'SigInput' with a 'ScriptOutput' of type 'PayPK'.
+arbitraryPKSigInput :: Network -> Gen (SigInput, SecKeyI)
+arbitraryPKSigInput net = arbitraryAnyInput net False
+
+-- | Arbitrary 'SigInput' with a 'ScriptOutput' of type 'PayPKHash'.
+arbitraryPKHashSigInput :: Network -> Gen (SigInput, SecKeyI)
+arbitraryPKHashSigInput net = arbitraryAnyInput net True
+
+arbitraryAnyInput :: Network -> Bool -> Gen (SigInput, SecKeyI)
+arbitraryAnyInput net pkh = do
+    (k, p) <- arbitraryKeyPair
+    let out | pkh = PayPKHash $ getAddrHash160 $ pubKeyAddr net p
+            | otherwise = PayPK p
+    (val, op, sh) <- arbitraryInputStuff net
+    return (SigInput out val op sh Nothing, k)
+
+arbitraryInputStuff :: Network -> Gen (Word64, OutPoint, SigHash)
+arbitraryInputStuff net = do
+    val <- getTestCoin <$> arbitrarySatoshi net
+    op <- arbitraryOutPoint
+    sh <- arbitraryValidSigHash net
+    return (val, op, sh)
+
+-- | Arbitrary 'SigInput' with a 'ScriptOutput' of type 'PayMulSig'.
+arbitraryMSSigInput :: Network -> Gen (SigInput, [SecKeyI])
+arbitraryMSSigInput net = do
+    (m, n) <- arbitraryMSParam
+    ks <- vectorOf n arbitraryKeyPair
+    let out = PayMulSig (map snd ks) m
+    (val, op, sh) <- arbitraryInputStuff net
+    perm <- choose (0, n - 1)
+    let ksPerm = map fst $ take m $ permutations ks !! perm
+    return (SigInput out val op sh Nothing, ksPerm)
+
+-- | Arbitrary 'SigInput' with 'ScriptOutput' of type 'PaySH' and a
+-- 'RedeemScript'.
+arbitrarySHSigInput :: Network -> Gen (SigInput, [SecKeyI])
+arbitrarySHSigInput net = do
+    (SigInput rdm val op sh _, ks) <- oneof
+        [ f <$> arbitraryPKSigInput net
+        , f <$> arbitraryPKHashSigInput net
+        , arbitraryMSSigInput net
+        ]
+    let out = PayScriptHash $ getAddrHash160 $ p2shAddr net rdm
+    return (SigInput out val op sh $ Just rdm, ks)
+  where
+    f (si, k) = (si, [k])
+
+-- | Arbitrary 'Tx' (empty 'TxIn'), 'SigInputs' and private keys that can be
+-- passed to 'signTx' or 'detSignTx' to fully sign the 'Tx'.
+arbitrarySigningData :: Network -> Gen (Tx, [SigInput], [SecKeyI])
+arbitrarySigningData net = do
+    v <- arbitrary
+    ni <- choose (1, 5)
+    no <- choose (1, 5)
+    sigis <- vectorOf ni (arbitrarySigInput net)
+    let uSigis = nubBy (\(a, _) (b, _) -> sigInputOP a == sigInputOP b) sigis
+    inps <- forM uSigis $ \(s, _) -> TxIn (sigInputOP s) BS.empty <$> arbitrary
+    outs <- vectorOf no (arbitraryTxOut net)
+    l <- arbitrary
+    perm <- choose (0, length inps - 1)
+    let tx = Tx v (permutations inps !! perm) outs [] l
+        keys = concatMap snd uSigis
+    return (tx, map fst uSigis, keys)
+
+-- | Arbitrary transaction with empty inputs.
+arbitraryEmptyTx :: Network -> Gen Tx
+arbitraryEmptyTx net = do
+    v    <- arbitrary
+    no   <- choose (1,5)
+    ni   <- choose (1,5)
+    outs <- vectorOf no (arbitraryTxOut net)
+    ops  <- vectorOf ni arbitraryOutPoint
+    t    <- arbitrary
+    s    <- arbitrary
+    return $ Tx v (map (\op -> TxIn op BS.empty s) (nub ops)) outs [] t
+
+-- | Arbitrary partially-signed transactions.
+arbitraryPartialTxs ::
+       Network -> Gen ([Tx], [(ScriptOutput, Word64, OutPoint, Int, Int)])
+arbitraryPartialTxs net = do
+    tx <- arbitraryEmptyTx net
+    res <-
+        forM (map prevOutput $ txIn tx) $ \op -> do
+            (so, val, rdmM, prvs, m, n) <- arbitraryData
+            txs <- mapM (singleSig so val rdmM tx op) prvs
+            return (txs, (so, val, op, m, n))
+    return (concatMap fst res, map snd res)
+  where
+    singleSig so val rdmM tx op prv = do
+        sh <- arbitraryValidSigHash net
+        let sigi = SigInput so val op sh rdmM
+        return . fromRight (error "Colud not decode transaction") $
+            signTx net tx [sigi] [prv]
+    arbitraryData = do
+        (m, n) <- arbitraryMSParam
+        val <- getTestCoin <$> arbitrarySatoshi net
+        nPrv <- choose (m, n)
+        keys <- vectorOf n arbitraryKeyPair
+        perm <- choose (0, length keys - 1)
+        let pubKeys = map snd keys
+            prvKeys = take nPrv $ permutations (map fst keys) !! perm
+        let so = PayMulSig pubKeys m
+        elements
+            [ (so, val, Nothing, prvKeys, m, n)
+            , ( PayScriptHash $ getAddrHash160 $ p2shAddr net so
+              , val
+              , Just so
+              , prvKeys
+              , m
+              , n)
+            ]
diff --git a/src/Network/Haskoin/Test/Util.hs b/src/Network/Haskoin/Test/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Test/Util.hs
@@ -0,0 +1,32 @@
+module Network.Haskoin.Test.Util where
+
+import           Data.ByteString       (ByteString, pack)
+import           Data.Time.Clock       (UTCTime (..))
+import           Data.Time.Clock.POSIX (posixSecondsToUTCTime)
+import           Data.Word             (Word32)
+import           Test.QuickCheck
+
+-- | Arbitrary strict 'ByteString'.
+arbitraryBS :: Gen ByteString
+arbitraryBS = pack <$> arbitrary
+
+-- | Arbitrary non-empty strict ByteString
+arbitraryBS1 :: Gen ByteString
+arbitraryBS1 = pack <$> listOf1 arbitrary
+
+-- | Arbitrary strict ByteString of a given length
+arbitraryBSn :: Int -> Gen ByteString
+arbitraryBSn n = pack <$> vectorOf n arbitrary
+
+-- | Arbitrary UTCTime that generates dates after 01 Jan 1970 01:00:00 CET
+arbitraryUTCTime :: Gen UTCTime
+arbitraryUTCTime = do
+    w <- arbitrary :: Gen Word32
+    return $ posixSecondsToUTCTime $ realToFrac w
+
+-- | Generate a Maybe from a Gen a
+arbitraryMaybe :: Gen a -> Gen (Maybe a)
+arbitraryMaybe g = frequency [ (1, return Nothing)
+                             , (5, Just <$> g)
+                             ]
+
diff --git a/src/Network/Haskoin/Transaction.hs b/src/Network/Haskoin/Transaction.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Transaction.hs
@@ -0,0 +1,11 @@
+{-|
+  This package provides functions for building and signing both simple
+  transactions and multisignature transactions.
+-}
+module Network.Haskoin.Transaction
+    ( module Common
+    , module Builder
+    ) where
+
+import           Network.Haskoin.Transaction.Builder as Builder
+import           Network.Haskoin.Transaction.Common  as Common
diff --git a/src/Network/Haskoin/Transaction/Builder.hs b/src/Network/Haskoin/Transaction/Builder.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Transaction/Builder.hs
@@ -0,0 +1,519 @@
+{-# LANGUAGE LambdaCase        #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Transaction.Builder
+    ( -- * Transaction Creation & Signing
+      buildAddrTx
+    , buildTx
+    , buildInput
+    , SigInput(..)
+    , signTx
+    , signInput
+    , verifyStdTx
+    , mergeTxs
+    , sigKeys
+    , mergeTxInput
+    , findSigInput
+    , verifyStdInput
+      -- * Coin Selection
+    , Coin(..)
+    , chooseCoins
+    , chooseCoinsSink
+    , chooseMSCoins
+    , chooseMSCoinsSink
+    , countMulSig
+    , greedyAddSink
+    , guessTxFee
+    , guessMSTxFee
+    , guessTxSize
+    , guessMSSize
+    ) where
+
+import           Control.Arrow                      (first)
+import           Control.DeepSeq                    (NFData, rnf)
+import           Control.Monad                      (foldM, mzero, unless, when)
+import           Control.Monad.Identity             (runIdentity)
+import           Data.Aeson                         (FromJSON, ToJSON,
+                                                     Value (Object), object,
+                                                     parseJSON, toJSON, (.:),
+                                                     (.:?), (.=))
+import           Data.ByteString                    (ByteString)
+import qualified Data.ByteString                    as BS
+import           Data.Conduit                       (ConduitT, Void, await,
+                                                     runConduit, (.|))
+import           Data.Conduit.List                  (sourceList)
+import           Data.List                          (find, nub)
+import           Data.Maybe                         (catMaybes, fromJust,
+                                                     fromMaybe, isJust,
+                                                     mapMaybe, maybeToList)
+import           Data.Serialize                     (encode)
+import           Data.String.Conversions            (cs)
+import           Data.Text                          (Text)
+import           Data.Word                          (Word64)
+import           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto.Signature
+import           Network.Haskoin.Keys.Common
+import           Network.Haskoin.Network.Common
+import           Network.Haskoin.Script
+import           Network.Haskoin.Transaction.Common
+import           Network.Haskoin.Util
+
+-- | Any type can be used as a Coin if it can provide a value in Satoshi.
+-- The value is used in coin selection algorithms.
+class Coin c where
+    coinValue :: c -> Word64
+
+-- | Coin selection algorithm for normal (non-multisig) transactions. This
+-- function returns the selected coins together with the amount of change to
+-- send back to yourself, taking the fee into account.
+chooseCoins :: Coin c
+            => Word64 -- ^ value to send
+            -> Word64 -- ^ fee per byte
+            -> Int    -- ^ number of outputs (including change)
+            -> Bool   -- ^ try to find better solutions
+            -> [c]    -- ^ list of ordered coins to choose from
+            -> Either String ([c], Word64)
+            -- ^ coin selection and change
+chooseCoins target fee nOut continue coins =
+    runIdentity . runConduit $
+    sourceList coins .| chooseCoinsSink target fee nOut continue
+
+-- | Coin selection algorithm for normal (non-multisig) transactions. This
+-- function returns the selected coins together with the amount of change to
+-- send back to yourself, taking the fee into account. This version uses a Sink
+-- for conduit-based coin selection.
+chooseCoinsSink :: (Monad m, Coin c)
+                => Word64 -- ^ value to send
+                -> Word64 -- ^ fee per byte
+                -> Int    -- ^ number of outputs (including change)
+                -> Bool   -- ^ try to find better solution
+                -> ConduitT c Void m (Either String ([c], Word64))
+                -- ^ coin selection and change
+chooseCoinsSink target fee nOut continue
+    | target > 0 =
+        maybeToEither err <$>
+            greedyAddSink target (guessTxFee fee nOut) continue
+    | otherwise = return $ Left "chooseCoins: Target must be > 0"
+  where
+    err = "chooseCoins: No solution found"
+
+-- | Coin selection algorithm for multisig transactions. This function returns
+-- the selected coins together with the amount of change to send back to
+-- yourself, taking the fee into account. This function assumes all the coins
+-- are script hash outputs that send funds to a multisignature address.
+chooseMSCoins :: Coin c
+              => Word64     -- ^ value to send
+              -> Word64     -- ^ fee per byte
+              -> (Int, Int) -- ^ m of n multisig
+              -> Int        -- ^ number of outputs (including change)
+              -> Bool       -- ^ try to find better solution
+              -> [c]
+              -> Either String ([c], Word64)
+              -- ^ coin selection change amount
+chooseMSCoins target fee ms nOut continue coins =
+    runIdentity . runConduit $
+        sourceList coins .| chooseMSCoinsSink target fee ms nOut continue
+
+-- | Coin selection algorithm for multisig transactions. This function returns
+-- the selected coins together with the amount of change to send back to
+-- yourself, taking the fee into account. This function assumes all the coins
+-- are script hash outputs that send funds to a multisignature address. This
+-- version uses a Sink if you need conduit-based coin selection.
+chooseMSCoinsSink :: (Monad m, Coin c)
+                  => Word64     -- ^ value to send
+                  -> Word64     -- ^ fee per byte
+                  -> (Int, Int) -- ^ m of n multisig
+                  -> Int        -- ^ number of outputs (including change)
+                  -> Bool       -- ^ try to find better solution
+                  -> ConduitT c Void m (Either String ([c], Word64))
+                  -- ^ coin selection and change
+chooseMSCoinsSink target fee ms nOut continue
+    | target > 0 =
+        maybeToEither err <$>
+            greedyAddSink target (guessMSTxFee fee ms nOut) continue
+    | otherwise = return $ Left "chooseMSCoins: Target must be > 0"
+  where
+    err = "chooseMSCoins: No solution found"
+
+-- | Select coins greedily by starting from an empty solution. If the 'continue'
+-- flag is set, the algorithm will try to find a better solution in the stream
+-- after a solution is found. If the next solution found is not strictly better
+-- than the previously found solution, the algorithm stops and returns the
+-- previous solution. If the continue flag is not set, the algorithm will return
+-- the first solution it finds in the stream.
+greedyAddSink :: (Monad m, Coin c)
+              => Word64          -- ^ value to send
+              -> (Int -> Word64) -- ^ coin count to fee function
+              -> Bool            -- ^ try to find better solutions
+              -> ConduitT c Void m (Maybe ([c], Word64))
+              -- ^ coin selection and change
+greedyAddSink target guessFee continue =
+    go [] 0 [] 0
+  where
+    -- The goal is the value we must reach (including the fee) for a certain
+    -- amount of selected coins.
+    goal c = target + guessFee c
+    go acc aTot ps pTot = await >>= \case
+        -- A coin is available in the stream
+        Just coin -> do
+            let val = coinValue coin
+            -- We have reached the goal using this coin
+            if val + aTot >= goal (length acc + 1)
+                -- If we want to continue searching for better solutions
+                then if continue
+                    -- This solution is the first one or
+                    -- This solution is better than the previous one
+                    then if pTot == 0 || val + aTot < pTot
+                        -- Continue searching for better solutions in the stream
+                        then go [] 0 (coin:acc) (val + aTot)
+                        -- Otherwise, we stop here and return the previous
+                        -- solution
+                        else return $ Just (ps, pTot - goal (length ps))
+                    -- Otherwise, return this solution
+                    else return $
+                        Just (coin : acc, val + aTot - goal (length acc + 1))
+                -- We have not yet reached the goal. Add the coin to the
+                -- accumulator
+                else go (coin:acc) (val + aTot) ps pTot
+        -- We reached the end of the stream
+        Nothing ->
+            return $ if null ps
+                -- If no solution was found, return Nothing
+                then Nothing
+                -- If we have a solution, return it
+                else Just (ps, pTot - goal (length ps))
+
+-- | Estimate tranasction fee to pay based on transaction size estimation.
+guessTxFee :: Word64 -> Int -> Int -> Word64
+guessTxFee byteFee nOut nIn =
+    byteFee * fromIntegral (guessTxSize nIn [] nOut 0)
+
+-- | Same as 'guessTxFee' but for multisig transactions.
+guessMSTxFee :: Word64 -> (Int, Int) -> Int -> Int -> Word64
+guessMSTxFee byteFee ms nOut nIn =
+    byteFee * fromIntegral (guessTxSize 0 (replicate nIn ms) nOut 0)
+
+-- | Computes an upper bound on the size of a transaction based on some known
+-- properties of the transaction.
+guessTxSize :: Int         -- ^ number of regular transaction inputs
+            -> [(Int,Int)] -- ^ multisig m of n for each input
+            -> Int         -- ^ number of P2PKH outputs
+            -> Int         -- ^ number of P2SH outputs
+            -> Int         -- ^ upper bound on transaction size
+guessTxSize pki msi pkout msout =
+    8 + inpLen + inp + outLen + out
+  where
+    inpLen = BS.length $ encode $ VarInt $ fromIntegral $ length msi + pki
+    outLen = BS.length $ encode $ VarInt $ fromIntegral $ pkout + msout
+    inp = pki * 148 + sum (map guessMSSize msi)
+             -- (20: hash160) + (5: opcodes) +
+             -- (1: script len) + (8: Word64)
+    out =
+        pkout * 34 +
+             -- (20: hash160) + (3: opcodes) +
+             -- (1: script len) + (8: Word64)
+        msout * 32
+
+-- | Size of a multisig P2SH input.
+guessMSSize :: (Int,Int) -> Int
+guessMSSize (m, n)
+    -- OutPoint (36) + Sequence (4) + Script
+ = 40 + fromIntegral (BS.length $ encode $ VarInt $ fromIntegral scp) + scp
+    -- OP_M + n*PubKey + OP_N + OP_CHECKMULTISIG
+  where
+    rdm =
+        fromIntegral $
+        BS.length $ encode $ opPushData $ BS.replicate (n * 34 + 3) 0
+    -- Redeem + m*sig + OP_0
+    scp = rdm + m * 73 + 1
+
+{- Build a new Tx -}
+
+-- | Build a transaction by providing a list of outpoints as inputs
+-- and a list of recipient addresses and amounts as outputs.
+buildAddrTx :: Network -> [OutPoint] -> [(Text, Word64)] -> Either String Tx
+buildAddrTx net xs ys = buildTx xs =<< mapM f ys
+  where
+    f (s, v) =
+        maybe (Left ("buildAddrTx: Invalid address " ++ cs s)) Right $ do
+            a <- stringToAddr net s
+            o <- addressToOutput a
+            return (o, v)
+
+-- | Build a transaction by providing a list of outpoints as inputs
+-- and a list of 'ScriptOutput' and amounts as outputs.
+buildTx :: [OutPoint] -> [(ScriptOutput, Word64)] -> Either String Tx
+buildTx xs ys =
+    mapM fo ys >>= \os -> return $ Tx 1 (map fi xs) os [] 0
+  where
+    fi outPoint = TxIn outPoint BS.empty maxBound
+    fo (o, v)
+        | v <= 2100000000000000 = return $ TxOut v $ encodeOutputBS o
+        | otherwise =
+            Left $ "buildTx: Invalid amount " ++ show v
+
+-- | Data type used to specify the signing parameters of a transaction input.
+-- To sign an input, the previous output script, outpoint and sighash are
+-- required. When signing a pay to script hash output, an additional redeem
+-- script is required.
+data SigInput = SigInput
+    { sigInputScript :: !ScriptOutput -- ^ output script to spend
+    , sigInputValue  :: !Word64       -- ^ output script value
+    , sigInputOP     :: !OutPoint     -- ^ outpoint to spend
+    , sigInputSH     :: !SigHash      -- ^ signature type
+    , sigInputRedeem :: !(Maybe RedeemScript) -- ^ sedeem script
+    } deriving (Eq, Show)
+
+instance NFData SigInput where
+    rnf (SigInput o v p h b) =
+        rnf o `seq` rnf v `seq` rnf p `seq` rnf h `seq` rnf b
+
+instance ToJSON SigInput where
+    toJSON (SigInput so val op sh rdm) = object $
+        [ "pkscript" .= so
+        , "value"    .= val
+        , "outpoint" .= op
+        , "sighash"  .= sh
+        ] ++ [ "redeem" .= r | r <- maybeToList rdm ]
+
+instance FromJSON SigInput where
+    parseJSON (Object o) = do
+        so  <- o .: "pkscript"
+        val <- o .: "value"
+        op  <- o .: "outpoint"
+        sh  <- o .: "sighash"
+        rdm <- o .:? "redeem"
+        return $ SigInput so val op sh rdm
+    parseJSON _ = mzero
+
+-- | Sign a transaction by providing the 'SigInput' signing parametres and a
+-- list of private keys. The signature is computed deterministically as defined
+-- in RFC-6979.
+signTx :: Network
+       -> Tx               -- ^ transaction to sign
+       -> [SigInput]       -- ^ signing parameters
+       -> [SecKeyI]        -- ^ wrapped private keys to sign with
+       -> Either String Tx -- ^ signed transaction
+signTx net otx sigis allKeys
+    | null ti   = Left "signTx: Transaction has no inputs"
+    | otherwise = foldM go otx $ findSigInput sigis ti
+  where
+    ti = txIn otx
+    go tx (sigi@(SigInput so _ _ _ rdmM), i) = do
+        keys <- sigKeys net so rdmM allKeys
+        foldM (\t k -> signInput net t i sigi k) tx keys
+
+-- | Sign a single input in a transaction deterministically (RFC-6979).
+signInput :: Network -> Tx -> Int -> SigInput -> SecKeyI -> Either String Tx
+signInput net tx i (SigInput so val _ sh rdmM) key = do
+    let sig = TxSignature (signHash (secKeyData key) msg) sh
+    si <- buildInput net tx i so val rdmM sig $ derivePubKeyI key
+    let ins = updateIndex i (txIn tx) (f si)
+    return $ Tx (txVersion tx) ins (txOut tx) [] (txLockTime tx)
+  where
+    f si x = x {scriptInput = encodeInputBS si}
+    msg = txSigHash net tx (encodeOutput $ fromMaybe so rdmM) val i sh
+
+-- | Order the 'SigInput' with respect to the transaction inputs. This allows
+-- the user to provide the 'SigInput' in any order. Users can also provide only
+-- a partial set of 'SigInput' entries.
+findSigInput :: [SigInput] -> [TxIn] -> [(SigInput, Int)]
+findSigInput si ti =
+    mapMaybe g $ zip (matchTemplate si ti f) [0..]
+  where
+    f s txin = sigInputOP s == prevOutput txin
+    g (Just s, i)  = Just (s,i)
+    g (Nothing, _) = Nothing
+
+-- | Find from the list of provided private keys which one is required to sign
+-- the 'ScriptOutput'.
+sigKeys ::
+       Network
+    -> ScriptOutput
+    -> Maybe RedeemScript
+    -> [SecKeyI]
+    -> Either String [SecKeyI]
+sigKeys net so rdmM keys =
+    case (so, rdmM) of
+        (PayPK p, Nothing) ->
+            return . map fst . maybeToList $ find ((== p) . snd) zipKeys
+        (PayPKHash h, Nothing) ->
+            return . map fst . maybeToList $
+            find ((== h) . getAddrHash160 . pubKeyAddr net . snd) zipKeys
+        (PayMulSig ps r, Nothing) ->
+            return $ map fst $ take r $ filter ((`elem` ps) . snd) zipKeys
+        (PayScriptHash _, Just rdm) -> sigKeys net rdm Nothing keys
+        _ -> Left "sigKeys: Could not decode output script"
+  where
+    zipKeys = map (\k -> (k, derivePubKeyI k)) keys
+
+-- | Construct an input for a transaction given a signature, public key and data
+-- about the previous output.
+buildInput ::
+       Network
+    -> Tx                 -- ^ transaction where input will be added
+    -> Int                -- ^ input index where signature will go
+    -> ScriptOutput       -- ^ output script being spent
+    -> Word64             -- ^ amount of previous output
+    -> Maybe RedeemScript -- ^ redeem script if pay-to-script-hash
+    -> TxSignature
+    -> PubKeyI
+    -> Either String ScriptInput
+buildInput net tx i so val rdmM sig pub = do
+    when (i >= length (txIn tx)) $ Left "buildInput: Invalid input index"
+    case (so, rdmM) of
+        (PayPK _, Nothing) -> return $ RegularInput $ SpendPK sig
+        (PayPKHash _, Nothing) -> return $ RegularInput $ SpendPKHash sig pub
+        (PayMulSig msPubs r, Nothing) -> do
+            let mSigs = take r $ catMaybes $ matchTemplate allSigs msPubs f
+            return $ RegularInput $ SpendMulSig mSigs
+        (PayScriptHash _, Just rdm) -> do
+            inp <- buildInput net tx i rdm val Nothing sig pub
+            return $ ScriptHashInput (getRegularInput inp) rdm
+        _ -> Left "buildInput: Invalid output/redeem script combination"
+  where
+    scp = scriptInput $ txIn tx !! i
+    allSigs =
+        nub $
+        sig :
+        case decodeInputBS net scp of
+            Right (ScriptHashInput (SpendMulSig xs) _) -> xs
+            Right (RegularInput (SpendMulSig xs))      -> xs
+            _                                          -> []
+    out = encodeOutput so
+    f (TxSignature x sh) p =
+        verifyHashSig (txSigHash net tx out val i sh) x (pubKeyPoint p)
+    f TxSignatureEmpty _ = False
+
+{- Merge multisig transactions -}
+
+-- | Merge partially-signed multisig transactions.
+mergeTxs :: Network -> [Tx] -> [(ScriptOutput, Word64, OutPoint)] -> Either String Tx
+mergeTxs net txs os
+    | null txs = error "Transaction list is empty"
+    | length (nub emptyTxs) /= 1 = Left "Transactions do not match"
+    | length txs == 1 = return $ head txs
+    | otherwise = foldM (mergeTxInput net txs) (head emptyTxs) outs
+  where
+    zipOp = zip (matchTemplate os (txIn $ head txs) f) [0..]
+    outs = map (first $ (\(o,v,_) -> (o,v)) . fromJust) $ filter (isJust . fst) zipOp
+    f (_, _, o) txin = o == prevOutput txin
+    emptyTxs = map (\tx -> foldl clearInput tx outs) txs
+    ins is i = updateIndex i is (\ti -> ti{ scriptInput = BS.empty })
+    clearInput tx (_, i) =
+        Tx (txVersion tx) (ins (txIn tx) i) (txOut tx) [] (txLockTime tx)
+
+-- | Merge input from partially-signed multisig transactions.
+mergeTxInput ::
+       Network
+    -> [Tx]
+    -> Tx
+    -> ((ScriptOutput, Word64), Int)
+    -> Either String Tx
+mergeTxInput net txs tx ((so, val), i)
+    -- Ignore transactions with empty inputs
+ = do
+    let ins = map (scriptInput . (!! i) . txIn) txs
+    sigRes <- mapM extractSigs $ filter (not . BS.null) ins
+    let rdm = snd $ head sigRes
+    unless (all (== rdm) $ map snd sigRes) $ Left "Redeem scripts do not match"
+    si <- encodeInputBS <$> go (nub $ concatMap fst sigRes) so rdm
+    let ins' = updateIndex i (txIn tx) (\ti -> ti {scriptInput = si})
+    return $ Tx (txVersion tx) ins' (txOut tx) [] (txLockTime tx)
+  where
+    go allSigs out rdmM =
+        case out of
+            PayMulSig msPubs r ->
+                let sigs =
+                        take r $
+                        catMaybes $ matchTemplate allSigs msPubs $ f out
+                 in return $ RegularInput $ SpendMulSig sigs
+            PayScriptHash _ ->
+                case rdmM of
+                    Just rdm -> do
+                        si <- go allSigs rdm Nothing
+                        return $ ScriptHashInput (getRegularInput si) rdm
+                    _ -> Left "Invalid output script type"
+            _ -> Left "Invalid output script type"
+    extractSigs si =
+        case decodeInputBS net si of
+            Right (RegularInput (SpendMulSig sigs)) -> Right (sigs, Nothing)
+            Right (ScriptHashInput (SpendMulSig sigs) rdm) ->
+                Right (sigs, Just rdm)
+            _ -> Left "Invalid script input type"
+    f out (TxSignature x sh) p =
+        verifyHashSig
+            (txSigHash net tx (encodeOutput out) val i sh)
+            x
+            (pubKeyPoint p)
+    f _ TxSignatureEmpty _ = False
+
+{- Tx verification -}
+
+-- | Verify if a transaction is valid and all of its inputs are standard.
+verifyStdTx :: Network -> Tx -> [(ScriptOutput, Word64, OutPoint)] -> Bool
+verifyStdTx net tx xs =
+    not (null (txIn tx)) && all go (zip (matchTemplate xs (txIn tx) f) [0 ..])
+  where
+    f (_, _, o) txin = o == prevOutput txin
+    go (Just (so, val, _), i) = verifyStdInput net tx i so val
+    go _                      = False
+
+-- | Verify if a transaction input is valid and standard.
+verifyStdInput :: Network -> Tx -> Int -> ScriptOutput -> Word64 -> Bool
+verifyStdInput net tx i = go (scriptInput $ txIn tx !! i)
+  where
+    dec = decodeInputBS net
+    go inp so val =
+        case dec inp of
+            Right (RegularInput (SpendPK (TxSignature sig sh))) ->
+                case so of
+                    PayPK pub ->
+                        verifyHashSig
+                            (txSigHash net tx out val i sh)
+                            sig
+                            (pubKeyPoint pub)
+                    _ -> False
+            Right (RegularInput (SpendPKHash (TxSignature sig sh) pub)) ->
+                case so of
+                    PayPKHash h ->
+                        pubKeyAddr net pub == PubKeyAddress h net &&
+                        verifyHashSig
+                            (txSigHash net tx out val i sh)
+                            sig
+                            (pubKeyPoint pub)
+                    _ -> False
+            Right (RegularInput (SpendMulSig sigs)) ->
+                case so of
+                    PayMulSig pubs r ->
+                        countMulSig net tx out val i (map pubKeyPoint pubs) sigs ==
+                        r
+                    _ -> False
+            Right (ScriptHashInput si rdm) ->
+                case so of
+                    PayScriptHash h ->
+                        p2shAddr net rdm == ScriptAddress h net &&
+                        go (encodeInputBS $ RegularInput si) rdm val
+                    _ -> False
+            _ -> False
+      where
+        out = encodeOutput so
+
+-- | Count the number of valid signatures for a multi-signature transaction.
+countMulSig ::
+       Network
+    -> Tx
+    -> Script
+    -> Word64
+    -> Int
+    -> [PubKey]
+    -> [TxSignature]
+    -> Int
+countMulSig _ _ _ _ _ [] _  = 0
+countMulSig _ _ _ _ _ _  [] = 0
+countMulSig net tx out val i (_:pubs) (TxSignatureEmpty:rest) =
+    countMulSig net tx out val i pubs rest
+countMulSig net tx out val i (pub:pubs) sigs@(TxSignature sig sh:rest)
+    | verifyHashSig (txSigHash net tx out val i sh) sig pub =
+        1 + countMulSig net tx out val i pubs rest
+    | otherwise = countMulSig net tx out val i pubs sigs
diff --git a/src/Network/Haskoin/Transaction/Common.hs b/src/Network/Haskoin/Transaction/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Transaction/Common.hs
@@ -0,0 +1,311 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE OverloadedStrings          #-}
+module Network.Haskoin.Transaction.Common
+    ( Tx(..)
+    , TxIn(..)
+    , TxOut(..)
+    , OutPoint(..)
+    , TxHash(..)
+    , WitnessData
+    , WitnessStack
+    , WitnessStackItem
+    , txHash
+    , hexToTxHash
+    , txHashToHex
+    , nosigTxHash
+    , nullOutPoint
+    , genesisTx
+    ) where
+
+import           Control.Applicative            ((<|>))
+import           Control.DeepSeq                (NFData, rnf)
+import           Control.Monad                  (forM_, guard, liftM2, mzero,
+                                                 replicateM, (<=<))
+import           Data.Aeson                     as A
+import           Data.ByteString                (ByteString)
+import qualified Data.ByteString                as B
+import           Data.Hashable                  (Hashable)
+import           Data.Maybe                     (fromMaybe, maybe)
+import           Data.Serialize                 as S
+import           Data.String                    (IsString, fromString)
+import           Data.String.Conversions        (cs)
+import           Data.Text                      (Text)
+import           Data.Word                      (Word32, Word64)
+import           Network.Haskoin.Crypto.Hash
+import           Network.Haskoin.Network.Common
+import           Network.Haskoin.Script.Common
+import           Network.Haskoin.Util
+import           Text.Read                      as R
+
+-- | Transaction id: hash of transaction excluding witness data.
+newtype TxHash = TxHash { getTxHash :: Hash256 }
+    deriving (Eq, Ord, NFData, Hashable, Serialize)
+
+instance Show TxHash where
+    showsPrec _ = shows . txHashToHex
+
+instance Read TxHash where
+    readPrec = do
+        R.String str <- R.lexP
+        maybe R.pfail return $ hexToTxHash $ cs str
+
+instance IsString TxHash where
+    fromString s =
+        let e = error "Could not read transaction hash from hex string"
+        in fromMaybe e $ hexToTxHash $ cs s
+
+instance FromJSON TxHash where
+    parseJSON = withText "txid" $
+        maybe mzero return . hexToTxHash
+
+instance ToJSON TxHash where
+    toJSON = A.String . txHashToHex
+
+-- | Transaction hash excluding signatures.
+nosigTxHash :: Tx -> TxHash
+nosigTxHash tx =
+    TxHash $ doubleSHA256 $ S.encode tx { txIn = map clearInput $ txIn tx }
+  where
+    clearInput ti = ti { scriptInput = B.empty }
+
+-- | Convert transaction hash to hex form, reversing bytes.
+txHashToHex :: TxHash -> Text
+txHashToHex (TxHash h) = encodeHex (B.reverse (S.encode h))
+
+-- | Convert transaction hash from hex, reversing bytes.
+hexToTxHash :: Text -> Maybe TxHash
+hexToTxHash hex = do
+    bs <- B.reverse <$> decodeHex hex
+    h <- either (const Nothing) Just (S.decode bs)
+    return $ TxHash 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
+      txVersion  :: !Word32
+      -- | list of transaction inputs
+    , txIn       :: ![TxIn]
+      -- | list of transaction outputs
+    , txOut      :: ![TxOut]
+      -- | witness data for the transaction
+    , txWitness  :: !WitnessData
+      -- | earliest mining height or time
+    , txLockTime :: !Word32
+    } deriving (Eq, Ord)
+
+-- | Compute transaction hash.
+txHash :: Tx -> TxHash
+txHash tx = TxHash (doubleSHA256 (S.encode tx {txWitness = []}))
+
+instance Show Tx where
+    showsPrec _ = shows . encodeHex . S.encode
+
+instance Read Tx where
+    readPrec = do
+        R.String str <- R.lexP
+        maybe R.pfail return $ (eitherToMaybe . S.decode) =<< decodeHex (cs str)
+
+instance IsString Tx where
+    fromString =
+        fromMaybe e . (eitherToMaybe . S.decode <=< decodeHex) . cs
+      where
+        e = error "Could not read transaction from hex string"
+
+instance NFData Tx where
+    rnf (Tx v i o w l) = rnf v `seq` rnf i `seq` rnf o `seq` rnf w `seq` rnf l
+
+instance Serialize Tx where
+    get = parseWitnessTx <|> parseLegacyTx
+    put tx
+        | null (txWitness tx) = putLegacyTx tx
+        | otherwise = putWitnessTx tx
+
+putInOut :: Tx -> Put
+putInOut tx = do
+    put $ VarInt $ fromIntegral $ length (txIn tx)
+    forM_ (txIn tx) put
+    put $ VarInt $ fromIntegral $ length (txOut tx)
+    forM_ (txOut tx) put
+
+-- | Non-SegWit transaction serializer.
+putLegacyTx :: Tx -> Put
+putLegacyTx tx = do
+    putWord32le (txVersion tx)
+    putInOut tx
+    putWord32le (txLockTime tx)
+
+-- | Witness transaciton serializer.
+putWitnessTx :: Tx -> Put
+putWitnessTx tx = do
+    putWord32le (txVersion tx)
+    putWord8 0x00
+    putWord8 0x01
+    putInOut tx
+    putWitnessData (txWitness tx)
+    putWord32le (txLockTime tx)
+
+-- | Non-SegWit transaction deseralizer.
+parseLegacyTx :: Get Tx
+parseLegacyTx = do
+    v <- getWord32le
+    is <- replicateList =<< S.get
+    os <- replicateList =<< S.get
+    l <- getWord32le
+    return
+        Tx
+        {txVersion = v, txIn = is, txOut = os, txWitness = [], txLockTime = l}
+  where
+    replicateList (VarInt c) = replicateM (fromIntegral c) S.get
+
+-- | Witness transaction deserializer.
+parseWitnessTx :: Get Tx
+parseWitnessTx = do
+    v <- getWord32le
+    m <- getWord8
+    f <- getWord8
+    guard $ m == 0x00
+    guard $ f == 0x01
+    is <- replicateList =<< S.get
+    os <- replicateList =<< S.get
+    w <- parseWitnessData $ length is
+    l <- getWord32le
+    return
+        Tx {txVersion = v, txIn = is, txOut = os, txWitness = w, txLockTime = l}
+  where
+    replicateList (VarInt c) = replicateM (fromIntegral c) S.get
+
+-- | Witness data deserializer. Requires count of inputs.
+parseWitnessData :: Int -> Get WitnessData
+parseWitnessData n = replicateM n parseWitnessStack
+  where
+    parseWitnessStack = do
+        VarInt i <- S.get
+        replicateM (fromIntegral i) parseWitnessStackItem
+    parseWitnessStackItem = do
+        VarInt i <- S.get
+        getByteString $ fromIntegral i
+
+-- | Witness data serializer.
+putWitnessData :: WitnessData -> Put
+putWitnessData = mapM_ putWitnessStack
+  where
+    putWitnessStack ws = do
+        put $ VarInt $ fromIntegral $ length ws
+        mapM_ putWitnessStackItem ws
+    putWitnessStackItem bs = do
+        put $ VarInt $ fromIntegral $ B.length bs
+        putByteString bs
+
+instance FromJSON Tx where
+    parseJSON = withText "Tx" $
+        maybe mzero return . (eitherToMaybe . S.decode <=< decodeHex)
+
+instance ToJSON Tx where
+    toJSON = A.String . encodeHex . S.encode
+
+-- | Data type representing a transaction input.
+data TxIn =
+    TxIn {
+           -- | output being spent
+           prevOutput   :: !OutPoint
+           -- | signatures and redeem script
+         , scriptInput  :: !ByteString
+           -- | lock-time using sequence numbers (BIP-68)
+         , txInSequence :: !Word32
+         } deriving (Eq, Show, Ord)
+
+instance NFData TxIn where
+    rnf (TxIn p i s) = rnf p `seq` rnf i `seq` rnf s
+
+instance Serialize TxIn where
+    get =
+        TxIn <$> S.get <*> (readBS =<< S.get) <*> getWord32le
+      where
+        readBS (VarInt len) = getByteString $ fromIntegral len
+
+    put (TxIn o s q) = do
+        put o
+        put $ VarInt $ fromIntegral $ B.length s
+        putByteString s
+        putWord32le q
+
+-- | Data type representing a transaction output.
+data TxOut =
+    TxOut {
+            -- | value of output is satoshi
+            outValue     :: !Word64
+            -- | pubkey script
+          , scriptOutput :: !ByteString
+          } deriving (Eq, Show, Ord)
+
+instance NFData TxOut where
+    rnf (TxOut v o) = rnf v `seq` rnf o
+
+instance Serialize TxOut where
+    get = do
+        val <- getWord64le
+        (VarInt len) <- S.get
+        TxOut val <$> getByteString (fromIntegral len)
+
+    put (TxOut o s) = do
+        putWord64le o
+        put $ VarInt $ fromIntegral $ B.length s
+        putByteString s
+
+-- | The 'OutPoint' refers to a transaction output being spent.
+data OutPoint = OutPoint
+    { -- | hash of previous transaction
+      outPointHash  :: !TxHash
+      -- | position of output in previous transaction
+    , outPointIndex :: !Word32
+    } deriving (Show, Read, Eq, Ord)
+
+instance NFData OutPoint where
+    rnf (OutPoint h i) = rnf h `seq` rnf i
+
+instance FromJSON OutPoint where
+    parseJSON = withText "OutPoint" $
+        maybe mzero return . (eitherToMaybe . S.decode <=< decodeHex)
+
+instance ToJSON OutPoint where
+    toJSON = A.String . encodeHex . S.encode
+
+instance Serialize OutPoint where
+    get = do
+        (h,i) <- liftM2 (,) S.get getWord32le
+        return $ OutPoint h i
+    put (OutPoint h i) = put h >> putWord32le i
+
+-- | Outpoint used in coinbase transactions.
+nullOutPoint :: OutPoint
+nullOutPoint =
+    OutPoint
+    { outPointHash =
+          "0000000000000000000000000000000000000000000000000000000000000000"
+    , outPointIndex = maxBound
+    }
+
+-- | Transaction from Genesis block.
+genesisTx :: Tx
+genesisTx =
+    Tx 1 [txin] [txout] [] locktime
+  where
+    txin = TxIn outpoint inputBS maxBound
+    txout = TxOut 5000000000 (encodeOutputBS output)
+    locktime = 0
+    outpoint = OutPoint z maxBound
+    Just inputBS = decodeHex $ fromString $
+        "04ffff001d0104455468652054696d65732030332f4a616e2f323030392043686" ++
+        "16e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f" ++
+        "757420666f722062616e6b73"
+    output = PayPK $ fromString $
+        "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb" ++
+        "649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"
+    z = "0000000000000000000000000000000000000000000000000000000000000000"
diff --git a/src/Network/Haskoin/Util.hs b/src/Network/Haskoin/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Haskoin/Util.hs
@@ -0,0 +1,194 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-|
+  This module defines various utility functions used across the
+  Network.Haskoin modules.
+-}
+module Network.Haskoin.Util
+    (
+      -- * ByteString Helpers
+      bsToInteger
+    , integerToBS
+    , encodeHex
+    , decodeHex
+    , getBits
+
+      -- * Maybe & Either Helpers
+    , eitherToMaybe
+    , maybeToEither
+    , liftEither
+    , liftMaybe
+
+      -- * Other Helpers
+    , updateIndex
+    , matchTemplate
+    , convertBits
+
+      -- * Triples
+    , fst3
+    , snd3
+    , lst3
+
+      -- * JSON Utilities
+    , dropFieldLabel
+    , dropSumLabels
+
+    ) where
+
+import           Control.Monad          (guard)
+import           Control.Monad.Except   (ExceptT (..))
+import           Data.Aeson.Types       (Options (..), SumEncoding (..),
+                                         defaultOptions, defaultTaggedObject)
+import           Data.Bits
+import           Data.ByteString        (ByteString)
+import qualified Data.ByteString        as BS
+import qualified Data.ByteString.Base16 as B16
+import           Data.Char              (toLower)
+import           Data.List
+import           Data.Text              (Text)
+import qualified Data.Text.Encoding     as E
+import           Data.Word              (Word8)
+
+-- ByteString helpers
+
+-- | Decode a big endian 'Integer' from a 'ByteString'.
+bsToInteger :: ByteString -> Integer
+bsToInteger = BS.foldr f 0 . BS.reverse
+  where
+    f w n = toInteger w .|. shiftL n 8
+
+-- | Encode an 'Integer' to a 'ByteString' as big endian.
+integerToBS :: Integer -> ByteString
+integerToBS 0 = BS.pack [0]
+integerToBS i
+    | i > 0     = BS.reverse $ BS.unfoldr f i
+    | otherwise = error "integerToBS not defined for negative values"
+  where
+    f 0 = Nothing
+    f x = Just (fromInteger x :: Word8, x `shiftR` 8)
+
+-- | Encode as string of human-readable hex characters.
+encodeHex :: ByteString -> Text
+encodeHex = E.decodeUtf8 . B16.encode
+
+-- | Decode string of human-readable hex characters.
+decodeHex :: Text -> Maybe ByteString
+decodeHex text =
+    let (x, b) = B16.decode (E.encodeUtf8 text)
+    in guard (b == BS.empty) >> return x
+
+-- | Obtain 'Int' bits from beginning of 'ByteString'. Resulting 'ByteString'
+-- will be smallest required to hold that many bits, padded with zeroes to the
+-- right.
+getBits :: Int -> ByteString -> ByteString
+getBits b bs
+    | r == 0 = BS.take q bs
+    | otherwise = i `BS.snoc` l
+  where
+    (q, r) = b `quotRem` 8
+    s = BS.take (q + 1) bs
+    i = BS.init s
+    l = BS.last s .&. (0xff `shiftL` (8 - r)) -- zero unneeded bits
+
+-- Maybe and Either monad helpers
+
+-- | Transform an 'Either' value into a 'Maybe' value. 'Right' is mapped to
+-- 'Just' and 'Left' is mapped to 'Nothing'. The value inside 'Left' is lost.
+eitherToMaybe :: Either a b -> Maybe b
+eitherToMaybe (Right b) = Just b
+eitherToMaybe _         = Nothing
+
+-- | Transform a 'Maybe' value into an 'Either' value. 'Just' is mapped to
+-- 'Right' and 'Nothing' is mapped to 'Left'. Default 'Left' required.
+maybeToEither :: b -> Maybe a -> Either b a
+maybeToEither err = maybe (Left err) Right
+
+-- | Lift a 'Either' computation into the 'ExceptT' monad.
+liftEither :: Monad m => Either b a -> ExceptT b m a
+liftEither = ExceptT . return
+
+-- | Lift a 'Maybe' computation into the 'ExceptT' monad.
+liftMaybe :: Monad m => b -> Maybe a -> ExceptT b m a
+liftMaybe err = liftEither . maybeToEither err
+
+-- Various helpers
+
+-- | Applies a function to only one element of a list defined by its index.  If
+-- the index is out of the bounds of the list, the original list is returned.
+updateIndex :: Int      -- ^ index of the element to change
+            -> [a]      -- ^ list of elements
+            -> (a -> a) -- ^ function to apply
+            -> [a]      -- ^ result with one element changed
+updateIndex i xs f
+    | i < 0 || i >= length xs = xs
+    | otherwise = l ++ (f h : r)
+  where
+    (l,h:r) = splitAt i xs
+
+-- | Use the list @[b]@ as a template and try to match the elements of @[a]@
+-- against it. For each element of @[b]@ return the (first) matching element of
+-- @[a]@, or 'Nothing'. Output list has same size as @[b]@ and contains results
+-- in same order. Elements of @[a]@ can only appear once.
+matchTemplate :: [a]              -- ^ input list
+              -> [b]              -- ^ list to serve as a template
+              -> (a -> b -> Bool) -- ^ comparison function
+              -> [Maybe a]
+matchTemplate [] bs _ = replicate (length bs) Nothing
+matchTemplate _  [] _ = []
+matchTemplate as (b:bs) f = case break (`f` b) as of
+    (l,r:rs) -> Just r  : matchTemplate (l ++ rs) bs f
+    _        -> Nothing : matchTemplate as bs f
+
+-- | Returns the first value of a triple.
+fst3 :: (a,b,c) -> a
+fst3 (a,_,_) = a
+
+-- | Returns the second value of a triple.
+snd3 :: (a,b,c) -> b
+snd3 (_,b,_) = b
+
+-- | Returns the last value of a triple.
+lst3 :: (a,b,c) -> c
+lst3 (_,_,c) = c
+
+-- | Field label goes lowercase and first @n@ characters get removed.
+dropFieldLabel :: Int -> Options
+dropFieldLabel n = defaultOptions
+    { fieldLabelModifier = map toLower . drop n
+    }
+
+-- | Transformation from 'dropFieldLabel' is applied with argument @f@, plus
+-- constructor tags are lowercased and first @c@ characters removed. @tag@ is
+-- used as the name of the object field name that will hold the transformed
+-- constructor tag as its value.
+dropSumLabels :: Int -> Int -> String -> Options
+dropSumLabels c f tag = (dropFieldLabel f)
+    { constructorTagModifier = map toLower . drop c
+    , sumEncoding = defaultTaggedObject { tagFieldName = tag }
+    }
+
+-- | Convert from one power-of-two base to another, as long as it fits in a
+-- 'Word'.
+convertBits :: Bool -> Int -> Int -> [Word] -> ([Word], Bool)
+convertBits pad frombits tobits i = (reverse yout, rem')
+  where
+    (xacc, xbits, xout) = foldl' outer (0, 0, []) i
+    (yout, rem')
+        | pad && xbits /= 0 =
+            let xout' = (xacc `shiftL` (tobits - xbits)) .&. maxv : xout
+            in (xout', False)
+        | pad = (xout, False)
+        | xbits /= 0 = (xout, True)
+        | otherwise = (xout, False)
+    maxv = 1 `shiftL` tobits - 1
+    max_acc = 1 `shiftL` (frombits + tobits - 1) - 1
+    outer (acc, bits, out) it =
+        let acc' = ((acc `shiftL` frombits) .|. it) .&. max_acc
+            bits' = bits + frombits
+            (out', bits'') = inner acc' out bits'
+        in (acc', bits'', out')
+    inner acc out bits
+        | bits >= tobits =
+            let bits' = bits - tobits
+                out' = ((acc `shiftR` bits') .&. maxv) : out
+            in inner acc out' bits'
+        | otherwise = (out, bits)
diff --git a/test/Network/Haskoin/Address/Bech32Spec.hs b/test/Network/Haskoin/Address/Bech32Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/Address/Bech32Spec.hs
@@ -0,0 +1,143 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Address.Bech32Spec
+    ( spec
+    ) where
+
+import           Control.Monad
+import           Data.Bits                      (xor)
+import           Data.ByteString                (ByteString)
+import qualified Data.ByteString                as B
+import           Data.Char                      (chr, ord, toLower)
+import           Data.Maybe
+import           Data.String.Conversions
+import           Data.Text                      (Text, append, pack, snoc,
+                                                 uncons)
+import qualified Data.Text                      as T
+import           Data.Word                      (Word8)
+import           Network.Haskoin.Address
+import           Network.Haskoin.Address.Bech32
+import           Network.Haskoin.Util
+import           Test.Hspec
+import           Test.HUnit
+
+spec = do
+    describe "bech32 checksum" $ do
+        it "should have valid checksum" $ forM_ validChecksums testValidChecksum
+        it "should have invalid checksum" $
+            forM_ invalidChecksums testInvalidChecksum
+        it "should be a valid address" $ forM_ validAddresses testValidAddress
+        it "should be an invalid address" $
+            forM_ invalidAddresses testInvalidAddress
+    describe "more encoding/decoding cases" $ do
+        it "length > 90" $
+            assert $
+            isNothing $
+            bech32Encode "bc" (replicate 82 (word5 (1 :: Word8)))
+        it "segwit version bounds" $
+            assert $ isNothing $ segwitEncode "bc" 17 []
+        it "segwit prog len version 0" $
+            assert $ isNothing $ segwitEncode "bc" 0 (replicate 30 1)
+        it "segwit prog len version != 0" $
+            assert $ isJust $ segwitEncode "bc" 1 (replicate 30 1)
+        it "segwit prog len version != 0" $
+            assert $ isNothing $ segwitEncode "bc" 1 (replicate 41 1)
+        it "empty HRP encode" $ assert $ isNothing $ bech32Encode "" []
+        it "empty HRP encode" $
+            assert $ isNothing $ bech32Decode "10a06t8"
+        it "hrp lowercased" $
+            Just "hrp1g9xj8m" `shouldBe`
+            bech32Encode "HRP" []
+
+
+testValidChecksum :: Bech32 -> Assertion
+testValidChecksum checksum = case bech32Decode checksum of
+    Nothing                      -> assertFailure (show checksum)
+    Just (resultHRP, resultData) -> do
+        -- test that a corrupted checksum fails decoding.
+        let (hrp, rest)         = T.breakOnEnd "1" checksum
+            Just (first, rest') = uncons rest
+            checksumCorrupted   = (hrp `snoc` chr (ord first `xor` 1)) `append` rest'
+        assertBool (show checksum ++ " corrupted")
+            $ isNothing (bech32Decode checksumCorrupted)
+        -- test that re-encoding the decoded checksum results in the same checksum.
+        let checksumEncoded  = bech32Encode resultHRP resultData
+            expectedChecksum = Just $ T.toLower checksum
+        assertEqual (show checksum ++ " re-encode")
+                    expectedChecksum
+                    checksumEncoded
+
+testInvalidChecksum :: Bech32 -> Assertion
+testInvalidChecksum checksum =
+    assertBool (show checksum) (isNothing $ bech32Decode checksum)
+
+testValidAddress :: (Text, Text) -> Assertion
+testValidAddress (address, hexscript) = do
+    let address' = T.toLower address
+        hrp      = T.take 2 address'
+    case segwitDecode hrp address of
+        Nothing                -> assertFailure "decode failed"
+        Just (witver, witprog) -> do
+            assertEqual (show address)
+                        (decodeHex hexscript)
+                        (Just $ segwitScriptPubkey witver witprog)
+            assertEqual (show address)
+                        (Just address')
+                        (segwitEncode hrp witver witprog)
+
+testInvalidAddress :: Text -> Assertion
+testInvalidAddress address = do
+    assertBool (show address) (isNothing $ segwitDecode "bc" address)
+    assertBool (show address) (isNothing $ segwitDecode "tb" address)
+
+segwitScriptPubkey :: Word8 -> [Word8] -> ByteString
+segwitScriptPubkey witver witprog =
+    B.pack $ witver' : fromIntegral (length witprog) : witprog
+    where witver' = if witver == 0 then 0 else witver + 0x50
+
+validChecksums :: [Text]
+validChecksums =
+    [ "A12UEL5L"
+    , "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs"
+    , "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw"
+    , "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j"
+    , "split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w"
+    ]
+
+invalidChecksums :: [Text]
+invalidChecksums =
+    [ " 1nwldj5"
+    , "\DEL1axkwrx"
+    , "an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx"
+    , "pzry9x0s0muk"
+    , "1pzry9x0s0muk"
+    , "x1b4n0q5v"
+    , "li1dgmt3"
+    , "de1lg7wt\xFF"
+    ]
+
+validAddresses :: [(Text, Text)]
+validAddresses =
+    [ ("BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", "0014751e76e8199196d454941c45d1b3a323f1433bd6")
+    , ("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7"
+      ,"00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262")
+    , ("bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx"
+      ,"5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6")
+    , ("BC1SW50QA3JX3S", "6002751e")
+    , ("bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", "5210751e76e8199196d454941c45d1b3a323")
+    , ("tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy"
+      ,"0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433")
+    ]
+
+invalidAddresses :: [Text]
+invalidAddresses =
+    [ "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty"
+    , "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5"
+    , "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2"
+    , "bc1rw5uspcuh"
+    , "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90"
+    , "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P"
+    , "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7"
+    , "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du"
+    , "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv"
+    , "bc1gmk9yu"
+    ]
diff --git a/test/Network/Haskoin/Address/CashAddrSpec.hs b/test/Network/Haskoin/Address/CashAddrSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/Address/CashAddrSpec.hs
@@ -0,0 +1,247 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Address.CashAddrSpec (spec) where
+
+import           Control.Monad
+import           Data.ByteString                  (ByteString)
+import qualified Data.ByteString.Char8            as C
+import           Data.Maybe
+import           Data.String.Conversions
+import           Data.Text                        (Text)
+import           Network.Haskoin.Address
+import           Network.Haskoin.Address.CashAddr
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Util
+import           Test.Hspec
+import           Test.HUnit
+
+spec :: Spec
+spec = do
+  describe "cashaddr checksum test vectors" $ do
+    it "prefix:x64nx6hz" $ do
+      let mpb = cash32decode "prefix:x64nx6hz"
+      mpb `shouldBe` Just ("prefix", "")
+    it "p:gpf8m4h7" $ do
+      let mpb = cash32decode "p:gpf8m4h7"
+      mpb `shouldBe` Just ("p", "")
+    it "bitcoincash:qpzry9x8gf2tvdw0s3jn54khce6mua7lcw20ayyn" $ do
+      let mpb = cash32decode "bitcoincash:qpzry9x8gf2tvdw0s3jn54khce6mua7lcw20ayyn"
+      mpb `shouldBe` Just ("bitcoincash","\NULD2\DC4\199BT\182\&5\207\132e:V\215\198u\190w\223")
+    it "bchtest:testnetaddress4d6njnut" $ do
+      let mpb = cash32decode "bchtest:testnetaddress4d6njnut"
+      mpb `shouldBe` Just ("bchtest","^`\185\229}kG\152")
+    it "bchreg:555555555555555555555555555555555555555555555udxmlmrz" $ do
+      let mpb = cash32decode "bchreg:555555555555555555555555555555555555555555555udxmlmrz"
+      mpb `shouldBe` Just ("bchreg","\165)JR\148\165)JR\148\165)JR\148\165)JR\148\165)JR\148\165)J")
+
+  describe "cashaddr to base58 translation test vectors" $ do
+    it "1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu" $ do
+      let addr = base58ToCashAddr "1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu"
+      addr `shouldBe` Just "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"
+    it "1KXrWXciRDZUpQwQmuM1DbwsKDLYAYsVLR" $ do
+      let addr = base58ToCashAddr "1KXrWXciRDZUpQwQmuM1DbwsKDLYAYsVLR"
+      addr `shouldBe` Just "bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy"
+    it "16w1D5WRVKJuZUsSRzdLp9w3YGcgoxDXb" $ do
+      let addr = base58ToCashAddr "16w1D5WRVKJuZUsSRzdLp9w3YGcgoxDXb"
+      addr `shouldBe` Just "bitcoincash:qqq3728yw0y47sqn6l2na30mcw6zm78dzqre909m2r"
+    it "3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC" $ do
+      let addr = base58ToCashAddr "3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC"
+      addr `shouldBe` Just "bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq"
+    it "3LDsS579y7sruadqu11beEJoTjdFiFCdX4" $ do
+      let addr = base58ToCashAddr "3LDsS579y7sruadqu11beEJoTjdFiFCdX4"
+      addr `shouldBe` Just "bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e"
+    it "31nwvkZwyPdgzjBJZXfDmSWsC4ZLKpYyUw" $ do
+      let addr = base58ToCashAddr "31nwvkZwyPdgzjBJZXfDmSWsC4ZLKpYyUw"
+      addr `shouldBe` Just "bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37"
+
+  describe "base58 to cashaddr translation test vectors" $ do
+    it "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a" $ do
+      let addr = cashAddrtoBase58 "bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"
+      addr `shouldBe` Just "1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu"
+    it "bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy" $ do
+      let addr = cashAddrtoBase58 "bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy"
+      addr `shouldBe` Just "1KXrWXciRDZUpQwQmuM1DbwsKDLYAYsVLR"
+    it "bitcoincash:qqq3728yw0y47sqn6l2na30mcw6zm78dzqre909m2r" $ do
+      let addr = cashAddrtoBase58 "bitcoincash:qqq3728yw0y47sqn6l2na30mcw6zm78dzqre909m2r"
+      addr `shouldBe` Just "16w1D5WRVKJuZUsSRzdLp9w3YGcgoxDXb"
+    it "bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq" $ do
+      let addr = cashAddrtoBase58 "bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq"
+      addr `shouldBe` Just "3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC"
+    it "bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e" $ do
+      let addr = cashAddrtoBase58 "bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e"
+      addr `shouldBe` Just "3LDsS579y7sruadqu11beEJoTjdFiFCdX4"
+    it "bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37" $ do
+      let addr = cashAddrtoBase58 "bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37"
+      addr `shouldBe` Just "31nwvkZwyPdgzjBJZXfDmSWsC4ZLKpYyUw"
+
+  describe "cashaddr larger test vectors" $
+      forM_ (zip [0..] vectors) $ \(i, vec) ->
+          it ("cashaddr test vector " <> show i) $ testCashAddr vec
+
+{- Various utilities -}
+
+base58ToCashAddr :: Text -> Maybe Text
+base58ToCashAddr b58 = fromBase58 b58 >>= toCashAddr
+  where
+    fromBase58 = stringToAddr btc
+    toCashAddr a = addrToString a { getAddrNet = bch }
+
+cashAddrtoBase58 :: Text -> Maybe Text
+cashAddrtoBase58 c32 = fromCashAddr c32 >>= toBase58
+  where
+    fromCashAddr = stringToAddr bch
+    toBase58 a = addrToString a { getAddrNet = btc }
+
+testCashAddr :: (Int, CashVersion, Cash32, Text) -> Assertion
+testCashAddr (len, typ, addr, hex) = do
+    let mbs = decodeHex hex
+    assertBool "Could not decode hex payload from test vector" (isJust mbs)
+    let Just bs = mbs
+    let mlow = cash32decode addr
+    assertBool "Could not decode low level address" (isJust mlow)
+    let Just (lpfx, lbs) = mlow
+    assertEqual "Low-level payload size incorrect" len (C.length lbs - 1)
+    assertEqual "Low-level payload doesn't match" bs (C.tail lbs)
+    let mdec = cash32decodeType addr
+    assertBool ("Could not decode test address: " <> cs addr) (isJust mdec)
+    let Just (pfx, ver, pay) = mdec
+    assertEqual "Length doesn't match" len (C.length pay)
+    assertEqual "Version doesn't match" typ ver
+    assertEqual "Payload doesn't match" bs pay
+  where
+    Just bs = decodeHex hex
+    Just (pfx, ver, pay) = cash32decodeType addr
+
+-- | All vectors starting with @pref@ had the wrong version in the spec
+-- document.
+vectors :: [(Int, CashVersion, Text, Text)]
+vectors =
+    [ ( 20
+      , 0
+      , "bitcoincash:qr6m7j9njldwwzlg9v7v53unlr4jkmx6eylep8ekg2"
+      , "F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9")
+    , ( 20
+      , 1
+      , "bchtest:pr6m7j9njldwwzlg9v7v53unlr4jkmx6eyvwc0uz5t"
+      , "F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9")
+    , ( 20
+      , 1
+      , "pref:pr6m7j9njldwwzlg9v7v53unlr4jkmx6ey65nvtks5"
+      , "F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9")
+    , ( 20
+      , 15
+      , "prefix:0r6m7j9njldwwzlg9v7v53unlr4jkmx6ey3qnjwsrf"
+      , "F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9")
+    , ( 24
+      , 0
+      , "bitcoincash:q9adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2ws4mr9g0"
+      , "7ADBF6C17084BC86C1706827B41A56F5CA32865925E946EA")
+    , ( 24
+      , 1
+      , "bchtest:p9adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2u94tsynr"
+      , "7ADBF6C17084BC86C1706827B41A56F5CA32865925E946EA")
+    , ( 24
+      , 1
+      , "pref:p9adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2khlwwk5v"
+      , "7ADBF6C17084BC86C1706827B41A56F5CA32865925E946EA")
+    , ( 24
+      , 15
+      , "prefix:09adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2p29kc2lp"
+      , "7ADBF6C17084BC86C1706827B41A56F5CA32865925E946EA")
+    , ( 28
+      , 0
+      , "bitcoincash:qgagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkcw59jxxuz"
+      , "3A84F9CF51AAE98A3BB3A78BF16A6183790B18719126325BFC0C075B")
+    , ( 28
+      , 1
+      , "bchtest:pgagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkcvs7md7wt"
+      , "3A84F9CF51AAE98A3BB3A78BF16A6183790B18719126325BFC0C075B")
+    , ( 28
+      , 1
+      , "pref:pgagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkcrsr6gzkn"
+      , "3A84F9CF51AAE98A3BB3A78BF16A6183790B18719126325BFC0C075B")
+    , ( 28
+      , 15
+      , "prefix:0gagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkc5djw8s9g"
+      , "3A84F9CF51AAE98A3BB3A78BF16A6183790B18719126325BFC0C075B")
+    , ( 32
+      , 0
+      , "bitcoincash:qvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq5nlegake"
+      , "3173EF6623C6B48FFD1A3DCC0CC6489B0A07BB47A37F47CFEF4FE69DE825C060")
+    , ( 32
+      , 1
+      , "bchtest:pvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq7fqng6m6"
+      , "3173EF6623C6B48FFD1A3DCC0CC6489B0A07BB47A37F47CFEF4FE69DE825C060")
+    , ( 32
+      , 1
+      , "pref:pvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq4k9m7qf9"
+      , "3173EF6623C6B48FFD1A3DCC0CC6489B0A07BB47A37F47CFEF4FE69DE825C060")
+    , ( 32
+      , 15
+      , "prefix:0vch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxqsh6jgp6w"
+      , "3173EF6623C6B48FFD1A3DCC0CC6489B0A07BB47A37F47CFEF4FE69DE825C060")
+    , ( 40
+      , 0
+      , "bitcoincash:qnq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklv39gr3uvz"
+      , "C07138323E00FA4FC122D3B85B9628EA810B3F381706385E289B0B25631197D194B5C238BEB136FB")
+    , ( 40
+      , 1
+      , "bchtest:pnq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklvmgm6ynej"
+      , "C07138323E00FA4FC122D3B85B9628EA810B3F381706385E289B0B25631197D194B5C238BEB136FB")
+    , ( 40
+      , 1
+      , "pref:pnq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklv0vx5z0w3"
+      , "C07138323E00FA4FC122D3B85B9628EA810B3F381706385E289B0B25631197D194B5C238BEB136FB")
+    , ( 40
+      , 15
+      , "prefix:0nq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklvwsvctzqy"
+      , "C07138323E00FA4FC122D3B85B9628EA810B3F381706385E289B0B25631197D194B5C238BEB136FB")
+    , ( 48
+      , 0
+      , "bitcoincash:qh3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqex2w82sl"
+      , "E361CA9A7F99107C17A622E047E3745D3E19CF804ED63C5C40C6BA763696B98241223D8CE62AD48D863F4CB18C930E4C")
+    , ( 48
+      , 1
+      , "bchtest:ph3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqnzf7mt6x"
+      , "E361CA9A7F99107C17A622E047E3745D3E19CF804ED63C5C40C6BA763696B98241223D8CE62AD48D863F4CB18C930E4C")
+    , ( 48
+      , 1
+      , "pref:ph3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqjntdfcwg"
+      , "E361CA9A7F99107C17A622E047E3745D3E19CF804ED63C5C40C6BA763696B98241223D8CE62AD48D863F4CB18C930E4C")
+    , ( 48
+      , 15
+      , "prefix:0h3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqakcssnmn"
+      , "E361CA9A7F99107C17A622E047E3745D3E19CF804ED63C5C40C6BA763696B98241223D8CE62AD48D863F4CB18C930E4C")
+    , ( 56
+      , 0
+      , "bitcoincash:qmvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqscw8jd03f"
+      , "D9FA7C4C6EF56DC4FF423BAAE6D495DBFF663D034A72D1DC7D52CBFE7D1E6858F9D523AC0A7A5C34077638E4DD1A701BD017842789982041")
+    , ( 56
+      , 1
+      , "bchtest:pmvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqs6kgdsg2g"
+      , "D9FA7C4C6EF56DC4FF423BAAE6D495DBFF663D034A72D1DC7D52CBFE7D1E6858F9D523AC0A7A5C34077638E4DD1A701BD017842789982041")
+    , ( 56
+      , 1
+      , "pref:pmvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqsammyqffl"
+      , "D9FA7C4C6EF56DC4FF423BAAE6D495DBFF663D034A72D1DC7D52CBFE7D1E6858F9D523AC0A7A5C34077638E4DD1A701BD017842789982041")
+    , ( 56
+      , 15
+      , "prefix:0mvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqsgjrqpnw8"
+      , "D9FA7C4C6EF56DC4FF423BAAE6D495DBFF663D034A72D1DC7D52CBFE7D1E6858F9D523AC0A7A5C34077638E4DD1A701BD017842789982041")
+    , ( 64
+      , 0
+      , "bitcoincash:qlg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96mtky5sv5w"
+      , "D0F346310D5513D9E01E299978624BA883E6BDA8F4C60883C10F28C2967E67EC77ECC7EEEAEAFC6DA89FAD72D11AC961E164678B868AEEEC5F2C1DA08884175B")
+    , ( 64
+      , 1
+      , "bchtest:plg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96mc773cwez"
+      , "D0F346310D5513D9E01E299978624BA883E6BDA8F4C60883C10F28C2967E67EC77ECC7EEEAEAFC6DA89FAD72D11AC961E164678B868AEEEC5F2C1DA08884175B")
+    , ( 64
+      , 1
+      , "pref:plg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96mg7pj3lh8"
+      , "D0F346310D5513D9E01E299978624BA883E6BDA8F4C60883C10F28C2967E67EC77ECC7EEEAEAFC6DA89FAD72D11AC961E164678B868AEEEC5F2C1DA08884175B")
+    , ( 64
+      , 15
+      , "prefix:0lg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96ms92w6845"
+      , "D0F346310D5513D9E01E299978624BA883E6BDA8F4C60883C10F28C2967E67EC77ECC7EEEAEAFC6DA89FAD72D11AC961E164678B868AEEEC5F2C1DA08884175B")
+    ]
diff --git a/test/Network/Haskoin/AddressSpec.hs b/test/Network/Haskoin/AddressSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/AddressSpec.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.AddressSpec (spec) where
+
+import           Data.Aeson
+import           Data.Aeson.Types
+import           Data.ByteString                (ByteString)
+import qualified Data.ByteString                as BS (append, empty, pack)
+import           Data.Text                      (Text)
+import           Network.Haskoin.Address
+import           Network.Haskoin.Address.Base58
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Test
+import           Test.Hspec
+import           Test.HUnit                     (Assertion, assertBool)
+import           Test.QuickCheck
+
+spec :: Spec
+spec = do
+    let net = btc
+    describe "btc address" $
+        it "base58 encodings" $ mapM_ runVector vectors
+    describe "btc-test address" $ props btcTest
+    describe "bch address" $ props bch
+    describe "bch-test address" $ props bchTest
+    describe "bch-regtest address" $ props bchRegTest
+    describe "json serialization" $
+        it "encodes and decodes address" $
+            forAll (arbitraryAddress net) (testCustom (addrFromJSON net))
+
+props :: Network -> Spec
+props net = do
+    it "encodes and decodes base58 bytestring" $
+        property $
+        forAll arbitraryBS $ \bs -> decodeBase58 (encodeBase58 bs) == Just bs
+    it "encodes and decodes base58 bytestring with checksum" $
+        property $
+        forAll arbitraryBS $ \bs ->
+            decodeBase58Check (encodeBase58Check bs) == Just bs
+    it "encodes and decodes address" $
+        property $
+        forAll (arbitraryAddress net) $ \a ->
+            (stringToAddr net =<< addrToString a) == Just a
+    it "shows and reads address" $
+        property $ forAll (arbitraryAddress net) $ \a -> read (show a) == a
+
+runVector :: (ByteString, Text, Text) -> Assertion
+runVector (bs, e, chk) = do
+    assertBool "encodeBase58" $ e == b58
+    assertBool "encodeBase58Check" $ chk == b58Chk
+    assertBool "decodeBase58" $ Just bs == decodeBase58 b58
+    assertBool "decodeBase58Check" $ Just bs == decodeBase58Check b58Chk
+  where
+    b58    = encodeBase58 bs
+    b58Chk = encodeBase58Check bs
+
+vectors :: [(ByteString, Text, Text)]
+vectors =
+    [ ( BS.empty, "", "3QJmnh" )
+    , ( BS.pack [0], "1", "1Wh4bh" )
+    , ( BS.pack [0,0,0,0], "1111", "11114bdQda" )
+    , ( BS.pack [0,0,1,0,0], "11LUw", "113CUwsFVuo" )
+    , ( BS.pack [255], "5Q", "VrZDWwe" )
+    , ( BS.pack [0,0,0,0] `BS.append` BS.pack [1..255]
+      , "1111cWB5HCBdLjAuqGGReWE3R3CguuwSjw6RHn39s2yuDRTS5NsBgNiFpWgAnEx6VQi8csexkgYw3mdYrMHr8x9i7aEwP8kZ7vccXWqKDvGv3u1GxFKPuAkn8JCPPGDMf3vMMnbzm6Nh9zh1gcNsMvH3ZNLmP5fSG6DGbbi2tuwMWPthr4boWwCxf7ewSgNQeacyozhKDDQQ1qL5fQFUW52QKUZDZ5fw3KXNQJMcNTcaB723LchjeKun7MuGW5qyCBZYzA1KjofN1gYBV3NqyhQJ3Ns746GNuf9N2pQPmHz4xpnSrrfCvy6TVVz5d4PdrjeshsWQwpZsZGzvbdAdN8MKV5QsBDY"
+      , "111151KWPPBRzdWPr1ASeu172gVgLf1YfUp6VJyk6K9t4cLqYtFHcMa2iX8S3NJEprUcW7W5LvaPRpz7UG7puBj5STE3nKhCGt5eckYq7mMn5nT7oTTic2BAX6zDdqrmGCnkszQkzkz8e5QLGDjf7KeQgtEDm4UER6DMSdBjFQVa6cHrrJn9myVyyhUrsVnfUk2WmNFZvkWv3Tnvzo2cJ1xW62XDfUgYz1pd97eUGGPuXvDFfLsBVd1dfdUhPwxW7pMPgdWHTmg5uqKGFF6vE4xXpAqZTbTxRZjCDdTn68c2wrcxApm8hq3JX65Hix7VtcD13FF8b7BzBtwjXq1ze6NMjKgUcqpJTN9vt"
+      )
+    ]
+
+testCustom :: (ToJSON a, Eq a) => (Value -> Parser a) -> a -> Bool
+testCustom f x = parseMaybe f (toJSON x) == Just x
diff --git a/test/Network/Haskoin/BlockSpec.hs b/test/Network/Haskoin/BlockSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/BlockSpec.hs
@@ -0,0 +1,347 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.BlockSpec
+    ( spec
+    ) where
+
+import           Control.Monad.State.Strict
+import           Data.Aeson                    as A
+import           Data.ByteString               (ByteString)
+import           Data.Either                   (fromRight)
+import           Data.Map.Strict               (singleton)
+import           Data.Maybe                    (fromJust)
+import           Data.Serialize                as S
+import           Data.String                   (fromString)
+import           Data.String.Conversions       (cs)
+import           Data.Text                     (Text)
+import           Network.Haskoin.Block
+import           Network.Haskoin.Block.Headers
+import           Network.Haskoin.Block.Merkle
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Test
+import           Network.Haskoin.Transaction
+import           Test.Hspec
+import           Test.HUnit                    hiding (State)
+import           Test.QuickCheck
+
+myTime :: Timestamp
+myTime = 1499083075
+
+withChain :: Network -> State HeaderMemory a -> a
+withChain net f = evalState f (initialChain net)
+
+chain :: BlockHeaders m => Network -> BlockHeader -> Int -> m ()
+chain net bh i = do
+    bnsE <- connectBlocks net myTime bhs
+    either error (const $ return ()) bnsE
+  where
+    bhs = appendBlocks net 6 bh i
+
+spec :: Spec
+spec = do
+    let net = bchRegTest
+    describe "blockchain headers" $ do
+        it "gets best block" $
+            let bb =
+                    withChain net $ do
+                        chain net (getGenesisHeader net) 100
+                        getBestBlockHeader
+             in nodeHeight bb `shouldBe` 100
+        it "builds a block locator" $
+            let net = bchRegTest
+                loc =
+                    withChain net $ do
+                        chain net (getGenesisHeader net) 100
+                        bb <- getBestBlockHeader
+                        blockLocatorNodes bb
+                heights = map nodeHeight loc
+             in heights `shouldBe` [100,99 .. 90] <> [88, 84, 76, 60, 28, 0]
+        it "follows split chains" $
+            let bb = withChain net $ splitChain net >> getBestBlockHeader
+             in nodeHeight bb `shouldBe` 4035
+    describe "block hash" $ do
+        it "encodes and decodes block hash" $
+            property $
+            forAll arbitraryBlockHash $ \h ->
+                hexToBlockHash (blockHashToHex h) == Just h
+        it "from string block hash" $
+            property $
+            forAll arbitraryBlockHash $ \h ->
+                fromString (cs $ blockHashToHex h) == h
+        it "show and read block hash" $
+            property $
+            forAll arbitraryBlockHash $ \h ->
+                read (show h) == h
+        it "json block hash" $ property $ forAll arbitraryBlockHash testID
+    describe "merkle trees" $ do
+        let net = btc
+        it "builds tree of right width at height 1" $ property testTreeWidth
+        it "builds tree of right width at height 0" $ property testBaseWidth
+        it "builds and extracts partial merkle tree" $
+            property $
+            forAll
+                (listOf1 ((,) <$> arbitraryTxHash <*> arbitrary))
+                (buildExtractTree net)
+        it "merkle root test vectors" $
+            zipWithM_ (curry mapMerkleVectors) merkleVectors [0 ..]
+    describe "compact number" $ do
+        it "compact number local vectors" testCompact
+        it "compact number imported vectors" testCompactBitcoinCore
+    describe "block serialization" $ do
+        it "encodes and decodes block" $
+            property $ forAll (arbitraryBlock net) cerealID
+        it "encodes and decodes block header" $
+            property $ forAll arbitraryBlockHeader cerealID
+        it "encodes and decodes getblocks" $
+            property $ forAll arbitraryGetBlocks cerealID
+        it "encodes and decodes getheaders" $
+            property $ forAll arbitraryGetHeaders cerealID
+        it "encodes and decdoes headers" $
+            property $ forAll arbitraryHeaders cerealID
+        it "encodes and decodes merkle block" $
+            property $ forAll arbitraryMerkleBlock cerealID
+
+-- 0 → → 2015 → → → → → → → 4031
+--       ↓
+--       → → 2035 → → → → → → 4035*
+--           ↓
+--           → → 2185
+splitChain :: Network -> State HeaderMemory ()
+splitChain net = do
+    start <- go 1 (getGenesisHeader net) 2015
+    e 2015 (head start)
+    tail1 <- go 2 (nodeHeader $ head start) 2016
+    e 4031 (head tail1)
+    tail2 <- go 3 (nodeHeader $ head start) 20
+    e 2035 (head tail2)
+    tail3 <- go 4 (nodeHeader $ head tail2) 2000
+    e 4035 (head tail3)
+    tail4 <- go 5 (nodeHeader $ head tail2) 150
+    e 2185 (head tail4)
+    sp1 <- splitPoint (head tail1) (head tail3)
+    unless (sp1 == head start) $
+        error $
+        "Split point wrong between blocks 4031 and 4035: " ++
+        show (nodeHeight sp1)
+    sp2 <- splitPoint (head tail4) (head tail3)
+    unless (sp2 == head tail2) $
+        error $
+        "Split point wrong between blocks 2185 and 4035: " ++
+        show (nodeHeight sp2)
+  where
+    e n bn =
+        unless (nodeHeight bn == n) $
+        error $
+        "Node height " ++
+        show (nodeHeight bn) ++ " of first chunk should be " ++ show n
+    go seed start n = do
+        let bhs = appendBlocks net seed start n
+        bnE <- connectBlocks net myTime bhs
+        case bnE of
+            Right bn -> return bn
+            Left ex  -> error ex
+
+{- Merkle Trees -}
+
+testTreeWidth :: Int -> Property
+testTreeWidth i = i /= 0 ==> calcTreeWidth (abs i) (calcTreeHeight $ abs i) == 1
+
+testBaseWidth :: Int -> Property
+testBaseWidth i = i /= 0 ==> calcTreeWidth (abs i) 0 == abs i
+
+buildExtractTree :: Network -> [(TxHash, Bool)] -> Bool
+buildExtractTree net txs =
+    r == buildMerkleRoot (map fst txs) && m == map fst (filter snd txs)
+  where
+    (f, h) = buildPartialMerkle txs
+    (r, m) =
+        fromRight (error "Could not extract matches from Merkle tree") $
+        extractMatches net f h (length txs)
+
+testCompact :: Assertion
+testCompact = do
+    assertEqual "vector 1" 0x05123456 (encodeCompact 0x1234560000)
+    assertEqual "vector 2" (0x1234560000, False) (decodeCompact 0x05123456)
+    assertEqual "vector 3" 0x0600c0de (encodeCompact 0xc0de000000)
+    assertEqual "vector 4" (0xc0de000000, False) (decodeCompact 0x0600c0de)
+    assertEqual "vector 5" 0x05c0de00 (encodeCompact (-0x40de000000))
+    assertEqual "vector 6" (-0x40de000000, False) (decodeCompact 0x05c0de00)
+
+testCompactBitcoinCore :: Assertion
+testCompactBitcoinCore = do
+    assertEqual "zero" (0, False) (decodeCompact 0x00000000)
+    assertEqual
+        "zero (encode · decode)"
+        0x00000000
+        (encodeCompact . fst $ decodeCompact 0x00000000)
+    assertEqual "rounds to zero" (0, False) (decodeCompact 0x00123456)
+    assertEqual "rounds to zero" (0, False) (decodeCompact 0x01003456)
+    assertEqual "rounds to zero" (0, False) (decodeCompact 0x02000056)
+    assertEqual "rounds to zero" (0, False) (decodeCompact 0x03000000)
+    assertEqual "rounds to zero" (0, False) (decodeCompact 0x04000000)
+    assertEqual "rounds to zero" (0, False) (decodeCompact 0x00923456)
+    assertEqual "rounds to zero" (0, False) (decodeCompact 0x01803456)
+    assertEqual "rounds to zero" (0, False) (decodeCompact 0x02800056)
+    assertEqual "rounds to zero" (0, False) (decodeCompact 0x03800000)
+    assertEqual "rounds to zero" (0, False) (decodeCompact 0x04800000)
+    assertEqual "vector 1 (decode)" (0x12, False) (decodeCompact 0x01123456)
+    assertEqual
+        "vector 1 (encode · decode)"
+        0x01120000
+        (encodeCompact . fst $ decodeCompact 0x01123456)
+    assertEqual "0x80 bit set" 0x02008000 (encodeCompact 0x80)
+    assertEqual
+        "vector 2 (negative) (decode)"
+        (-0x7e, False)
+        (decodeCompact 0x01fedcba)
+    assertEqual
+        "vector 2 (negative) (encode · decode)"
+        0x01fe0000
+        (encodeCompact . fst $ decodeCompact 0x01fedcba)
+    assertEqual "vector 3 (decode)" (0x1234, False) (decodeCompact 0x02123456)
+    assertEqual
+        "vector 3 (encode · decode)"
+        0x02123400
+        (encodeCompact . fst $ decodeCompact 0x02123456)
+    assertEqual "vector 4 (decode)" (0x123456, False) (decodeCompact 0x03123456)
+    assertEqual
+        "vector 4 (encode · decode)"
+        0x03123456
+        (encodeCompact . fst $ decodeCompact 0x03123456)
+    assertEqual
+        "vector 5 (decode)"
+        (0x12345600, False)
+        (decodeCompact 0x04123456)
+    assertEqual
+        "vector 5 (encode · decode)"
+        0x04123456
+        (encodeCompact . fst $ decodeCompact 0x04123456)
+    assertEqual
+        "vector 6 (decode)"
+        (-0x12345600, False)
+        (decodeCompact 0x04923456)
+    assertEqual
+        "vector 6 (encode · decode)"
+        0x04923456
+        (encodeCompact . fst $ decodeCompact 0x04923456)
+    assertEqual
+        "vector 7 (decode)"
+        (0x92340000, False)
+        (decodeCompact 0x05009234)
+    assertEqual
+        "vector 7 (encode · decode)"
+        0x05009234
+        (encodeCompact . fst $ decodeCompact 0x05009234)
+    assertEqual
+        "vector 8 (decode)"
+        ( 0x1234560000000000000000000000000000000000000000000000000000000000
+        , False)
+        (decodeCompact 0x20123456)
+    assertEqual
+        "vector 8 (encode · decode)"
+        0x20123456
+        (encodeCompact . fst $ decodeCompact 0x20123456)
+    assertBool "vector 9 (decode) (overflow)" (snd $ decodeCompact 0xff123456)
+    assertBool
+        "vector 9 (decode) (positive)"
+        ((> 0) . fst $ decodeCompact 0xff123456)
+
+mapMerkleVectors :: ((Text, [Text]), Int) -> Assertion
+mapMerkleVectors (v, i) = runMerkleVector v
+
+runMerkleVector :: (Text, [Text]) -> Assertion
+runMerkleVector (r, hs) =
+    assertBool "merkle vector" $
+        buildMerkleRoot (map f hs) == getTxHash (f r)
+  where
+    f = fromJust . hexToTxHash
+
+merkleVectors :: [(Text, [Text])]
+merkleVectors =
+      -- Block 000000000000cd7e8cf6510303dde76121a1a791c15dba0be4be7022b07cf9e1
+    [ ( "fb6698ac95b754256c5e71b4fbe07638cb6ca83ee67f44e181b91727f09f4b1f"
+      , [ "dd96fdcfaec994bf583af650ff6022980ee0ba1686d84d0a3a2d24eabf34bc52"
+        , "1bc216f786a564378710ae589916fc8e092ddfb9f24fe6c47b733550d476d5d9"
+        , "a1db0b0194426064b067899ff2d975fb277fd52dbb1a38370800c76dd6503d41"
+        , "d69f7fb0e668fbd437d1bf5211cc34d7eb8746f50cfddf705fe10bc2f8f7035f"
+        , "5b4057cd80be7df5ed2ac42b776897ed3c26e3a01e4072075b8129c587094ef6"
+        , "ed6dabcfba0ef43c50d89a8a0e4b236b1bc6585d4c3bbf49728b55f44312d6bc"
+        , "056aaa9a3c635909c794e9b0acc7dccb0456c59a84c6b08417335bee4515e3d3"
+        , "05bae5f1d1c874171692e1fc06f664e63eb143d3f096601ef938e4a9012eee66"
+        , "b5e48e94e3f2fba197b3f591e01f47e185d7834d669529d44078e41c671aab0f"
+        , "3b56aeadfc0c5484fd507bc89f13f2e5f61c42e0a4ae9062eda9a9aeef7db6a4"
+        , "2affa187e1ebb94a2a86578b9f64951e854ff3d346fef259acfb6d0f5212e0d3"
+        ]
+      )
+      -- Block 00000000000007cc4b6f07bfed72bccc1ed8dd031a93969a4c22211f784457d4
+    , ( "886fea311d2dc64c315519f2d647e43998d780d2170f77e53dc0d85bf2ee680c"
+      , [ "c9c9e5211512629fd111cc071d745b8c79bf486b4ea95489eb5de08b5d786b8e"
+        , "20beb0ee30dfd323ade790ce9a46ae7a174f9ea44ce22a17c4d4eb23b7016f51"
+        , "d4cb7dd741e78a8f57e12f6c8ddb0361ff2a5bf9365bd7d7df761060847daf9a"
+        , "ddbfa6fdd29d4b47aeaadf82a4bf0a93d58cd7d8401fabf860a1ae8eeb51f42e"
+        , "9d82bafe44abee248b968c86f165051c8413482c232659795335c52922dab471"
+        , "86035372d31b53efd848cea7231aa9738c209aff64d3c59b1619341afb5b6ba3"
+        , "11e7a7393d9658813dfaebc04fa6d4b73bac8d641bffa7067da879523d43d030"
+        , "2f676b9aa5bc0ebf3395032c84c466e40cac29f80434cd1138e31c2d0fcc5c13"
+        , "37567d559fbfae07fda9a90de0ce30b202128bc8ebdfef5ad2b53e865a3478c2"
+        , "0b8e6c1200c454361e94e261738429e9c9b8dcffd85ec8511bbf5dc7e2e0ada8"
+        ]
+      )
+      -- Block 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
+    , ( "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
+      , [ "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098" ]
+      )
+      -- Block 000000000004d160ac1f7b775d7c1823345aeadd5fcb29ca2ad2403bb7babd4c
+    , ( "aae018650f513fc42d55b2210ec3ceeeb194fb1261d37989de07451fc0cbac5c"
+      , [ "a4454f22831acd7904a9902c5070a3ee4bf4c2b13bc6b2dc66735dd3c4414028"
+        , "45297f334278885108dd38a0b689ed95a4373dd3f7e4413e6aebdc2654fb771b"
+        ]
+      )
+      -- Block 000000000001d1b13a7e86ddb20da178f20d6da5cd037a29c2a15b8b84cc774e
+    , ( "ca3580505feb87544760ac14a5859659e23be05f765bbed9f86a3c9aad1a5d0c"
+      , [ "60702384c6e9d34ff03c2b3e726bdc649befe603216815bd0a2974921d0d9549"
+        , "11f40f58941d2a81a1616a3b84b7dd8b9d07e68750827de488c11a18f54220bb"
+        , "d78e82527aa8cf16e375010bc666362c0258d3c0da1885a1871121706da8b633"
+        ]
+      )
+      -- Block 0000000000000630a4e2266a31776e952a19b7c99a6387917d9de9032f608021
+    , ( "dcce8be0a9a41e7bb726c5b49d957d90b5308e3dc5dce070ccbc8996e265a6c2"
+      , [ "c0f58ff12cd1023b05f8f7035cc62bf50958ddb216a4e0eb5471deb7ef25fe81"
+        , "24e5bbf9008641b8fcf3d076fef66c28c695362ba9f6a6042f8275a98414ee92"
+        , "e8e1f72abad5e34dabc0f6de46a484b17a9af857d1c41de19482fadf6f7f4b27"
+        , "540e4d34d9fd9e5ec02853054be7ad9260379bc23388489049cca1b0f7cf518a"
+        , "324444835c5fe0545f98c4240011b75e6ea1bb76f41829e4cfbe7f75b6cee924"
+        , "e7d31437ac21bceb0c222a82b2723e2b8a7654147e33397679f041537022a4b2"
+        , "a8b5768d8b33525ee89d546a6a6897f8e42ba9d56a2c5e871a5d2ab40258dc95"
+        , "7ba712b31bae8d45810a5cda3838c7e7fb9abd6e88bb4b3ee79be9ea2f714bb4"
+        , "2ae1c4d927b06edaa626b230976ad8062bbae24da9378d1de2409da5ab08a26d"
+        , "3c417dc8087d6878003624b74431e17fec9ca761389034b1b1e0f32cbfb11f4f"
+        , "de6de7beae8d8c98c7d46b4409d5460e58e3204d8b4caed256c7471998595909"
+        , "c7c3c211402b7c4379f7b01fadc67260ee58d11e8d0bcce3d68cb45f3467e99d"
+        , "77aa2717e727a096d81074bd46ae59462692d20a1acc1a01b2535518ae5aeb53"
+        , "4859a710bb673aca46208bbd59d1000ae990dafff5f70b56f0853aeeaea3948b"
+        , "38deca6991988e461b83aa0d49ffef0f304c4b760371682d152eeb8c56a48174"
+        , "648f4f50dada3574e2dfe2dc68956b01dd97d543859a3540bbe1ef5418d0e494"
+        , "9cd7be42c2f0cd8bf38738c162cd05108e213ec7958bf2571cb627872963f5c4"
+        , "6740e0dd8b97e23864af41839fc197238d2f0dbefce9a82c657556be65c465fa"
+        , "f75c2e4b70db4b0aabc44b77af1ae75d305340fcf6e7b5f806ddcba4aa42b55d"
+        , "e125c488636749da68e6696b97525a77146c0777c7946927e37afd513d74a4e6"
+        , "c20526f119aea10880af631eba7f0b60385a22e0b0c402fe8508d41952e58be9"
+        , "6456c023c7e245f5c57a168633a23f57f4fadb651115f807694a6bed14ae3b55"
+        , "98b26e364e2888c9f264e4b5e13103c89608609774eb07ce933d8a2a45d19776"
+        , "2efaa4f167bb65ba5684f8076cd9279fd67fd9c67388c8862809bab5542e637d"
+        , "ec44eeb84d8d976d77079a822710b4dfdb11a2d9a03d8cc00bab0ae424e84666"
+        , "410730d9f807d81ac48b8eafac6f1d36642c1c370241b367a35f0bac6ac7c05f"
+        , "e95a7d0d477fd3db22756a3fd390a50c7bc48dc9e946fea9d24bd0866b3bb0e9"
+        , "a72fec99d14939216628aaf7a0afc4c017113bcae964e777e6b508864eeaacc4"
+        , "8548433310fcf75dbbc042121e8318c678e0a017534786dd322a91cebe8d213f"
+        ]
+      )
+    ]
+
+testID :: (FromJSON a, ToJSON a, Eq a) => a -> Bool
+testID x =
+    (A.decode . A.encode) (singleton ("object" :: String) x) ==
+    Just (singleton ("object" :: String) x)
+
+cerealID :: (Serialize a, Eq a) => a -> Bool
+cerealID x = S.decode (S.encode x) == Right x
diff --git a/test/Network/Haskoin/Crypto/HashSpec.hs b/test/Network/Haskoin/Crypto/HashSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/Crypto/HashSpec.hs
@@ -0,0 +1,1269 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Crypto.HashSpec (spec) where
+
+import           Data.ByteString         (ByteString)
+import           Data.Map.Strict         (singleton)
+import           Data.Maybe              (fromJust)
+import           Data.Serialize          as S
+import           Data.String             (fromString)
+import           Data.String.Conversions
+import           Network.Haskoin.Block
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Test
+import           Network.Haskoin.Util
+import           Test.Hspec
+import           Test.HUnit              (Assertion, assertBool)
+import           Test.QuickCheck
+
+-- Test vectors from NIST
+-- http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+-- About 1/3 of HMAC DRBG SHA-256 test vectors are tested here
+
+spec :: Spec
+spec =
+    describe "hash" $ do
+        it "join512( split512(h) ) == h" $
+            property $
+            forAll arbitraryHash256 $ forAll arbitraryHash256 . joinSplit512
+        it "decodeCompact . encodeCompact i == i" $ property decEncCompact
+        it "from string 64-byte hash" $
+            property $
+            forAll arbitraryHash512 $ \h ->
+                fromString (cs $ encodeHex $ encode h) == h
+        it "from string 32-byte hash" $
+            property $
+            forAll arbitraryHash256 $ \h ->
+                fromString (cs $ encodeHex $ encode h) == h
+        it "from string 20-byte hash" $
+            property $
+            forAll arbitraryHash160 $ \h ->
+                fromString (cs $ encodeHex $ encode h) == h
+        it "encodes and decodes bytestring" $
+            property $ forAll arbitraryBS cerealID
+        it "encodes and decodes hash160" $
+            property $ forAll arbitraryHash160 cerealID
+        it "encodes and decodes hash256" $
+            property $ forAll arbitraryHash256 cerealID
+        it "encodes and decodes hash512" $
+            property $ forAll arbitraryHash512 cerealID
+
+type TestVector = [ByteString]
+
+{-
+    [SHA-256]
+    [PredictionResistance = False]
+    [EntropyInputLen = 256]
+    [NonceLen = 128]
+    [PersonalizationStringLen = 0]
+    [AdditionalInputLen = 0]
+    [ReturnedBitsLen = 1024]
+-}
+
+joinSplit512 :: Hash256 -> Hash256 -> Bool
+joinSplit512 a b = split512 (join512 (a, b)) == (a, b)
+
+-- After encoding and decoding, we may loose precision so the new result is >=
+-- to the old one.
+decEncCompact :: Integer -> Bool
+decEncCompact i
+    -- Integer completely fits inside the mantisse
+    | abs i <= 0x007fffff = decodeCompact (encodeCompact i) == (i, False)
+    -- Otherwise precision will be lost and the decoded result will
+    -- be smaller than the original number
+    | i >= 0              = fst (decodeCompact (encodeCompact i)) < i
+    | otherwise           = fst (decodeCompact (encodeCompact i)) > i
+
+cerealID :: (Serialize a, Eq a) => a -> Bool
+cerealID x = decode (encode x) == Right x
+
+t1 :: [TestVector]
+t1 =
+    [
+    -- COUNT = 0
+    [ "ca851911349384bffe89de1cbdc46e6831e44d34a4fb935ee285dd14b71a7488"
+    , "659ba96c601dc69fc902940805ec0ca8"
+    , ""
+    , ""
+    , ""
+    , "e528e9abf2dece54d47c7e75e5fe302149f817ea9fb4bee6f4199697d04d5b89d54fbb978a15b5c443c9ec21036d2460b6f73ebad0dc2aba6e624abf07745bc107694bb7547bb0995f70de25d6b29e2d3011bb19d27676c07162c8b5ccde0668961df86803482cb37ed6d5c0bb8d50cf1f50d476aa0458bdaba806f48be9dcb8"
+    ],
+    -- COUNT = 1
+    [ "79737479ba4e7642a221fcfd1b820b134e9e3540a35bb48ffae29c20f5418ea3"
+    , "3593259c092bef4129bc2c6c9e19f343"
+    , ""
+    , ""
+    , ""
+    , "cf5ad5984f9e43917aa9087380dac46e410ddc8a7731859c84e9d0f31bd43655b924159413e2293b17610f211e09f770f172b8fb693a35b85d3b9e5e63b1dc252ac0e115002e9bedfb4b5b6fd43f33b8e0eafb2d072e1a6fee1f159df9b51e6c8da737e60d5032dd30544ec51558c6f080bdbdab1de8a939e961e06b5f1aca37"
+    ],
+    -- COUNT = 2
+    [ "b340907445b97a8b589264de4a17c0bea11bb53ad72f9f33297f05d2879d898d"
+    , "65cb27735d83c0708f72684ea58f7ee5"
+    , ""
+    , ""
+    , ""
+    , "75183aaaf3574bc68003352ad655d0e9ce9dd17552723b47fab0e84ef903694a32987eeddbdc48efd24195dbdac8a46ba2d972f5808f23a869e71343140361f58b243e62722088fe10a98e43372d252b144e00c89c215a76a121734bdc485486f65c0b16b8963524a3a70e6f38f169c12f6cbdd169dd48fe4421a235847a23ff"
+    ],
+    -- COUNT = 3
+    [ "8e159f60060a7d6a7e6fe7c9f769c30b98acb1240b25e7ee33f1da834c0858e7"
+    , "c39d35052201bdcce4e127a04f04d644"
+    , ""
+    , ""
+    , ""
+    , "62910a77213967ea93d6457e255af51fc79d49629af2fccd81840cdfbb4910991f50a477cbd29edd8a47c4fec9d141f50dfde7c4d8fcab473eff3cc2ee9e7cc90871f180777a97841597b0dd7e779eff9784b9cc33689fd7d48c0dcd341515ac8fecf5c55a6327aea8d58f97220b7462373e84e3b7417a57e80ce946d6120db5"
+    ],
+    -- COUNT = 4
+    [ "74755f196305f7fb6689b2fe6835dc1d81484fc481a6b8087f649a1952f4df6a"
+    , "c36387a544a5f2b78007651a7b74b749"
+    , ""
+    , ""
+    , ""
+    , "b2896f3af4375dab67e8062d82c1a005ef4ed119d13a9f18371b1b873774418684805fd659bfd69964f83a5cfe08667ddad672cafd16befffa9faed49865214f703951b443e6dca22edb636f3308380144b9333de4bcb0735710e4d9266786342fc53babe7bdbe3c01a3addb7f23c63ce2834729fabbd419b47beceb4a460236"
+    ],
+    -- COUNT = 5
+    [ "4b222718f56a3260b3c2625a4cf80950b7d6c1250f170bd5c28b118abdf23b2f"
+    , "7aed52d0016fcaef0b6492bc40bbe0e9"
+    , ""
+    , ""
+    , ""
+    , "a6da029b3665cd39fd50a54c553f99fed3626f4902ffe322dc51f0670dfe8742ed48415cf04bbad5ed3b23b18b7892d170a7dcf3ef8052d5717cb0c1a8b3010d9a9ea5de70ae5356249c0e098946030c46d9d3d209864539444374d8fbcae068e1d6548fa59e6562e6b2d1acbda8da0318c23752ebc9be0c1c1c5b3cf66dd967"
+    ],
+    -- COUNT = 6
+    [ "b512633f27fb182a076917e39888ba3ff35d23c3742eb8f3c635a044163768e0"
+    , "e2c39b84629a3de5c301db5643af1c21"
+    , ""
+    , ""
+    , ""
+    , "fb931d0d0194a97b48d5d4c231fdad5c61aedf1c3a55ac24983ecbf38487b1c93396c6b86ff3920cfa8c77e0146de835ea5809676e702dee6a78100da9aa43d8ec0bf5720befa71f82193205ac2ea403e8d7e0e6270b366dc4200be26afd9f63b7e79286a35c688c57cbff55ac747d4c28bb80a2b2097b3b62ea439950d75dff"
+    ],
+    -- COUNT = 7
+    [ "aae3ffc8605a975befefcea0a7a286642bc3b95fb37bd0eb0585a4cabf8b3d1e"
+    , "9504c3c0c4310c1c0746a036c91d9034"
+    , ""
+    , ""
+    , ""
+    , "2819bd3b0d216dad59ddd6c354c4518153a2b04374b07c49e64a8e4d055575dfbc9a8fcde68bd257ff1ba5c6000564b46d6dd7ecd9c5d684fd757df62d85211575d3562d7814008ab5c8bc00e7b5a649eae2318665b55d762de36eba00c2906c0e0ec8706edb493e51ca5eb4b9f015dc932f262f52a86b11c41e9a6d5b3bd431"
+    ],
+    -- COUNT = 8
+    [ "b9475210b79b87180e746df704b3cbc7bf8424750e416a7fbb5ce3ef25a82cc6"
+    , "24baf03599c10df6ef44065d715a93f7"
+    , ""
+    , ""
+    , ""
+    , "ae12d784f796183c50db5a1a283aa35ed9a2b685dacea97c596ff8c294906d1b1305ba1f80254eb062b874a8dfffa3378c809ab2869aa51a4e6a489692284a25038908a347342175c38401193b8afc498077e10522bec5c70882b7f760ea5946870bd9fc72961eedbe8bff4fd58c7cc1589bb4f369ed0d3bf26c5bbc62e0b2b2"
+    ],
+    -- COUNT = 9
+    [ "27838eb44ceccb4e36210703ebf38f659bc39dd3277cd76b7a9bcd6bc964b628"
+    , "39cfe0210db2e7b0eb52a387476e7ea1"
+    , ""
+    , ""
+    , ""
+    , "e5e72a53605d2aaa67832f97536445ab774dd9bff7f13a0d11fd27bf6593bfb52309f2d4f09d147192199ea584503181de87002f4ee085c7dc18bf32ce5315647a3708e6f404d6588c92b2dda599c131aa350d18c747b33dc8eda15cf40e95263d1231e1b4b68f8d829f86054d49cfdb1b8d96ab0465110569c8583a424a099a"
+    ],
+    -- COUNT = 10
+    [ "d7129e4f47008ad60c9b5d081ff4ca8eb821a6e4deb91608bf4e2647835373a5"
+    , "a72882773f78c2fc4878295840a53012"
+    , ""
+    , ""
+    , ""
+    , "0cbf48585c5de9183b7ff76557f8fc9ebcfdfde07e588a8641156f61b7952725bbee954f87e9b937513b16bba0f2e523d095114658e00f0f3772175acfcb3240a01de631c19c5a834c94cc58d04a6837f0d2782fa53d2f9f65178ee9c837222494c799e64c60406069bd319549b889fa00a0032dd7ba5b1cc9edbf58de82bfcd"
+    ],
+    -- COUNT = 11
+    [ "67fe5e300c513371976c80de4b20d4473889c9f1214bce718bc32d1da3ab7532"
+    , "e256d88497738a33923aa003a8d7845c"
+    , ""
+    , ""
+    , ""
+    , "b44660d64ef7bcebc7a1ab71f8407a02285c7592d755ae6766059e894f694373ed9c776c0cfc8594413eefb400ed427e158d687e28da3ecc205e0f7370fb089676bbb0fa591ec8d916c3d5f18a3eb4a417120705f3e2198154cd60648dbfcfc901242e15711cacd501b2c2826abe870ba32da785ed6f1fdc68f203d1ab43a64f"
+    ],
+    -- COUNT = 12
+    [ "de8142541255c46d66efc6173b0fe3ffaf5936c897a3ce2e9d5835616aafa2cb"
+    , "d01f9002c407127bc3297a561d89b81d"
+    , ""
+    , ""
+    , ""
+    , "64d1020929d74716446d8a4e17205d0756b5264867811aa24d0d0da8644db25d5cde474143c57d12482f6bf0f31d10af9d1da4eb6d701bdd605a8db74fb4e77f79aaa9e450afda50b18d19fae68f03db1d7b5f1738d2fdce9ad3ee9461b58ee242daf7a1d72c45c9213eca34e14810a9fca5208d5c56d8066bab1586f1513de7"
+    ],
+    -- COUNT = 13
+    [ "4a8e0bd90bdb12f7748ad5f147b115d7385bb1b06aee7d8b76136a25d779bcb7"
+    , "7f3cce4af8c8ce3c45bdf23c6b181a00"
+    , ""
+    , ""
+    , ""
+    , "320c7ca4bbeb7af977bc054f604b5086a3f237aa5501658112f3e7a33d2231f5536d2c85c1dad9d9b0bf7f619c81be4854661626839c8c10ae7fdc0c0b571be34b58d66da553676167b00e7d8e49f416aacb2926c6eb2c66ec98bffae20864cf92496db15e3b09e530b7b9648be8d3916b3c20a3a779bec7d66da63396849aaf"
+    ],
+    -- COUNT = 14
+    [ "451ed024bc4b95f1025b14ec3616f5e42e80824541dc795a2f07500f92adc665"
+    , "2f28e6ee8de5879db1eccd58c994e5f0"
+    , ""
+    , ""
+    , ""
+    , "3fb637085ab75f4e95655faae95885166a5fbb423bb03dbf0543be063bcd48799c4f05d4e522634d9275fe02e1edd920e26d9accd43709cb0d8f6e50aa54a5f3bdd618be23cf73ef736ed0ef7524b0d14d5bef8c8aec1cf1ed3e1c38a808b35e61a44078127c7cb3a8fd7addfa50fcf3ff3bc6d6bc355d5436fe9b71eb44f7fd"
+    ]
+    ]
+
+{-
+    [SHA-256]
+    [PredictionResistance = False]
+    [EntropyInputLen = 256]
+    [NonceLen = 128]
+    [PersonalizationStringLen = 0]
+    [AdditionalInputLen = 256]
+    [ReturnedBitsLen = 1024]
+-}
+
+t2 :: [TestVector]
+t2 =
+    [
+    -- COUNT = 0
+    [ "d3cc4d1acf3dde0c4bd2290d262337042dc632948223d3a2eaab87da44295fbd"
+    , "0109b0e729f457328aa18569a9224921"
+    , ""
+    , "3c311848183c9a212a26f27f8c6647e40375e466a0857cc39c4e47575d53f1f6"
+    , "fcb9abd19ccfbccef88c9c39bfb3dd7b1c12266c9808992e305bc3cff566e4e4"
+    , "9c7b758b212cd0fcecd5daa489821712e3cdea4467b560ef5ddc24ab47749a1f1ffdbbb118f4e62fcfca3371b8fbfc5b0646b83e06bfbbab5fac30ea09ea2bc76f1ea568c9be0444b2cc90517b20ca825f2d0eccd88e7175538b85d90ab390183ca6395535d34473af6b5a5b88f5a59ee7561573337ea819da0dcc3573a22974"
+    ],
+    -- COUNT = 1
+    [ "f97a3cfd91faa046b9e61b9493d436c4931f604b22f1081521b3419151e8ff06"
+    , "11f3a7d43595357d58120bd1e2dd8aed"
+    , ""
+    , "517289afe444a0fe5ed1a41dbbb5eb17150079bdd31e29cf2ff30034d8268e3b"
+    , "88028d29ef80b4e6f0fe12f91d7449fe75062682e89c571440c0c9b52c42a6e0"
+    , "c6871cff0824fe55ea7689a52229886730450e5d362da5bf590dcf9acd67fed4cb32107df5d03969a66b1f6494fdf5d63d5b4d0d34ea7399a07d0116126d0d518c7c55ba46e12f62efc8fe28a51c9d428e6d371d7397ab319fc73ded4722e5b4f30004032a6128df5e7497ecf82ca7b0a50e867ef6728a4f509a8c859087039c"
+    ],
+    -- COUNT = 2
+    [ "0f2f23d64f481cabec7abb01db3aabf125c3173a044b9bf26844300b69dcac8b"
+    , "9a5ae13232b43aa19cfe8d7958b4b590"
+    , ""
+    , "ec4c7a62acab73385f567da10e892ff395a0929f959231a5628188ce0c26e818"
+    , "6b97b8c6b6bb8935e676c410c17caa8042aa3145f856d0a32b641e4ae5298648"
+    , "7480a361058bd9afa3db82c9d7586e42269102013f6ec5c269b6d05f17987847748684766b44918fd4b65e1648622fc0e0954178b0279dfc9fa99b66c6f53e51c4860131e9e0644287a4afe4ca8e480417e070db68008a97c3397e4b320b5d1a1d7e1d18a95cfedd7d1e74997052bf649d132deb9ec53aae7dafdab55e6dae93"
+    ],
+    -- COUNT = 3
+    [ "53c56660c78481be9c63284e005fcc14fbc7fb27732c9bf1366d01a426765a31"
+    , "dc7a14d0eb5b0b3534e717a0b3c64614"
+    , ""
+    , "3aa848706ecb877f5bedf4ffc332d57c22e08747a47e75cff6f0fd1316861c95"
+    , "9a401afa739b8f752fddacd291e0b854f5eff4a55b515e20cb319852189d3722"
+    , "5c0eb420e0bf41ce9323e815310e4e8303cd677a8a8b023f31f0d79f0ca15aeb636099a369fd074d69889865eac1b72ab3cbfebdb8cf460b00072802e2ec648b1349a5303be4ccaadd729f1a9ea17482fd026aaeb93f1602bc1404b9853adde40d6c34b844cf148bc088941ecfc1642c8c0b9778e45f3b07e06e21ee2c9e0300"
+    ],
+    -- COUNT = 4
+    [ "f63c804404902db334c54bb298fc271a21d7acd9f770278e089775710bf4fdd7"
+    , "3e45009ea9cb2a36ba1aa4bf39178200"
+    , ""
+    , "d165a13dc8cc43f3f0952c3f5d3de4136954d983683d4a3e6d2dc4c89bf23423"
+    , "75106bc86d0336df85097f6af8e80e2da59046a03fa65b06706b8bbc7ffc6785"
+    , "6363139bba32c22a0f5cd23ca6d437b5669b7d432f786b8af445471bee0b2d24c9d5f2f93717cbe00d1f010cc3b9c515fc9f7336d53d4d26ba5c0d76a90186663c8582eb739c7b6578a3328bf68dc2cec2cd89b3a90201f6993adcc854df0f5c6974d0f5570765a15fe03dbce28942dd2fd16ba2027e68abac83926969349af8"
+    ],
+    -- COUNT = 5
+    [ "2aaca9147da66c176615726b69e3e851cc3537f5f279fe7344233d8e44cfc99d"
+    , "4e171f080af9a6081bee9f183ac9e340"
+    , ""
+    , "d75a2a6eb66c3833e50f5ec3d2e434cf791448d618026d0c360806d120ded669"
+    , "b643b74c15b37612e6577ed7ca2a4c67a78d560af9eb50a4108fca742e87b8d6"
+    , "501dcdc977f4ba856f24eaa4968b374bebb3166b280334cb510232c31ebffde10fa47b7840ef3fe3b77725c2272d3a1d4219baf23e0290c622271edcced58838cf428f0517425d2e19e0d8c89377eecfc378245f283236fafa466c914b99672ceafab369e8889a0c866d8bd639db9fb797254262c6fd44cfa9045ad6340a60ef"
+    ],
+    -- COUNT = 6
+    [ "a2e4cd48a5cf918d6f55942d95fcb4e8465cdc4f77b7c52b6fae5b16a25ca306"
+    , "bef036716440db6e6d333d9d760b7ca8"
+    , ""
+    , "bfa591c7287f3f931168f95e38869441d1f9a11035ad8ea625bb61b9ea17591c"
+    , "c00c735463bca215adc372cb892b05e939bf669583341c06d4e31d0e5b363a37"
+    , "e7d136af69926a5421d4266ee0420fd729f2a4f7c295d3c966bdfa05268180b508b8a2852d1b3a06fd2ab3e13c54005123ef319f42d0c6d3a575e6e7e1496cb28aacadbcf83740fba8f35fcee04bb2ed8a51db3d3362b01094a62fb57e33c99a432f29fce6676cffbbcc05107e794e75e44a02d5e6d9d748c5fbff00a0178d65"
+    ],
+    -- COUNT = 7
+    [ "95a67771cba69011a79776e713145d309edae56fad5fd6d41d83eaff89df6e5e"
+    , "be5b5164e31ecc51ba6f7c3c5199eb33"
+    , ""
+    , "065f693b229a7c4fd373cd15b3807552dd9bf98c5485cef361949d4e7d774b53"
+    , "9afb62406f0e812c4f156d58b19a656c904813c1b4a45a0029ae7f50731f8014"
+    , "f61b61a6e79a41183e8ed6647899d2dc85cdaf5c3abf5c7f3bf37685946dc28f4923dc842f2d4326bd6ce0d50a84cb3ba869d72a36e246910eba6512ba36cd7ed3a5437c9245b00a344308c792b668b458d3c3e16dee2fbec41867da31084d46d8ec168de2148ef64fc5b72069abf5a6ada1ead2b7146bb793ff1c9c3690fa56"
+    ],
+    -- COUNT = 8
+    [ "a459e1815cbca4514ec8094d5ab2414a557ba6fe10e613c345338d0521e4bf90"
+    , "62221392e2552e76cd0d36df6e6068eb"
+    , ""
+    , "0a3642b02b23b3ef62c701a63401124022f5b896de86dab6e6c7451497aa1dcc"
+    , "c80514865901371c45ba92d9f95d50bb7c9dd1768cb3dfbc45b968da94965c6e"
+    , "464e6977b8adaef307c9623e41c357013249c9ffd77f405f3925cebb69f151ce8fbb6a277164002aee7858fc224f6499042aa1e6322deee9a5d133c31d640e12a7487c731ba03ad866a24675badb1d79220c40be689f79c2a0be93cb4dada3e0eac4ab140cb91998b6f11953e68f2319b050c40f71c34de9905ae41b2de1c2f6"
+    ],
+    -- COUNT = 9
+    [ "252c2cad613e002478162861880979ee4e323025eebb6fb2e0aa9f200e28e0a1"
+    , "d001bc9a8f2c8c242e4369df0c191989"
+    , ""
+    , "9bcfc61cb2bc000034bb3db980eb47c76fb5ecdd40553eff113368d639b947fd"
+    , "8b0565c767c2610ee0014582e9fbecb96e173005b60e9581503a6dca5637a26e"
+    , "e96c15fe8a60692b0a7d67171e0195ff6e1c87aab844221e71700d1bbee75feea695f6a740c9760bbe0e812ecf4061d8f0955bc0195e18c4fd1516ebca50ba6a6db86881737dbab8321707675479b87611db6af2c97ea361a5484555ead454defb1a64335de964fc803d40f3a6f057893d2afc25725754f4f00abc51920743dc"
+    ],
+    -- COUNT = 10
+    [ "8be0ca6adc8b3870c9d69d6021bc1f1d8eb9e649073d35ee6c5aa0b7e56ad8a5"
+    , "9d1265f7d51fdb65377f1e6edd6ae0e4"
+    , ""
+    , "da86167ac997c406bb7979f423986a84ec6614d6caa7afc10aff0699a9b2cf7f"
+    , "e4baa3c555950b53e2bfdba480cb4c94b59381bac1e33947e0c22e838a9534cf"
+    , "64384ecc4ea6b458efc227ca697eac5510092265520c0a0d8a0ccf9ed3ca9d58074671188c6a7ad16d0b050cdc072c125d7298d3a31d9f044a9ee40da0089a84fea28cc7f05f1716db952fad29a0e779635cb7a912a959be67be2f0a4170aace2981802e2ff6467e5b46f0ffbff3b42ba5935fd553c82482ac266acf1cd247d7"
+    ],
+    -- COUNT = 11
+    [ "d43a75b6adf26d60322284cb12ac38327792442aa8f040f60a2f331b33ac4a8f"
+    , "0682f8b091f811afacaacaec9b04d279"
+    , ""
+    , "7fd3b8f512940da7de5d80199d9a7b42670c04a945775a3dba869546cbb9bc65"
+    , "2575db20bc7aafc2a90a5dabab760db851d754777bc9f05616af1858b24ff3da"
+    , "0da7a8dc73c163014bf0841913d3067806456bbca6d5de92b85534c6545467313648d71ef17c923d090dc92cff8d4d1a9a2bb63e001dc2e8ab1a597999be3d6cf70ff63fee9985801395fbd4f4990430c4259fcae4fa1fcd73dc3187ccc102d04af7c07532885e5a226fc42809c48f22eecf4f6ab996ae4fcb144786957d9f41"
+    ],
+    -- COUNT = 12
+    [ "64352f236af5d32067a529a8fd05ba00a338c9de306371a0b00c36e610a48d18"
+    , "df99ed2c7608c870624b962a5dc68acd"
+    , ""
+    , "da416335e7aaf60cf3d06fb438735ce796aad09034f8969c8f8c3f81e32fef24"
+    , "a28c07c21a2297311adf172c19e83ca0a87731bdffb80548978d2d1cd82cf8a3"
+    , "132b9f25868729e3853d3c51f99a3b5fae6d4204bea70890daf62e042b776a526c8fb831b80a6d5d3f153237df1fd39b6fd9137963f5516d9cdd4e3f9195c46e9972c15d3edc6606e3368bde1594977fb88d0ca6e6f5f3d057ccadc7d7dab77dfc42658a1e972aa446b20d418286386a52dfc1c714d2ac548713268b0b709729"
+    ],
+    -- COUNT = 13
+    [ "282f4d2e05a2cd30e9087f5633089389449f04bac11df718c90bb351cd3653a5"
+    , "90a7daf3c0de9ea286081efc4a684dfb"
+    , ""
+    , "2630b4ccc7271cc379cb580b0aaede3d3aa8c1c7ba002cf791f0752c3d739007"
+    , "c31d69de499f1017be44e3d4fa77ecebc6a9b9934749fcf136f267b29115d2cc"
+    , "c899094520e0197c37b91dd50778e20a5b950decfb308d39f1db709447ae48f6101d9abe63a783fbb830eec1d359a5f61a2013728966d349213ee96382614aa4135058a967627183810c6622a2158cababe3b8ab99169c89e362108bf5955b4ffc47440f87e4bad0d36bc738e737e072e64d8842e7619f1be0af1141f05afe2d"
+    ],
+    -- COUNT = 14
+    [ "13c752b9e745ce77bbc7c0dbda982313d3fe66f903e83ebd8dbe4ff0c11380e9"
+    , "f1a533095d6174164bd7c82532464ae7"
+    , ""
+    , "4f53db89b9ba7fc00767bc751fb8f3c103fe0f76acd6d5c7891ab15b2b7cf67c"
+    , "582c2a7d34679088cca6bd28723c99aac07db46c332dc0153d1673256903b446"
+    , "6311f4c0c4cd1f86bd48349abb9eb930d4f63df5e5f7217d1d1b91a71d8a6938b0ad2b3e897bd7e3d8703db125fab30e03464fad41e5ddf5bf9aeeb5161b244468cfb26a9d956931a5412c97d64188b0da1bd907819c686f39af82e91cfeef0cbffb5d1e229e383bed26d06412988640706815a6e820796876f416653e464961"
+    ]
+    ]
+
+{-
+    [SHA-256]
+    [PredictionResistance = False]
+    [EntropyInputLen = 256]
+    [NonceLen = 128]
+    [PersonalizationStringLen = 256]
+    [AdditionalInputLen = 0]
+    [ReturnedBitsLen = 1024]
+-}
+
+t3 :: [TestVector]
+t3 =
+    [
+    -- COUNT = 0
+    [ "5cacc68165a2e2ee20812f35ec73a79dbf30fd475476ac0c44fc6174cdac2b55"
+    , "6f885496c1e63af620becd9e71ecb824"
+    , "e72dd8590d4ed5295515c35ed6199e9d211b8f069b3058caa6670b96ef1208d0"
+    , ""
+    , ""
+    , "f1012cf543f94533df27fedfbf58e5b79a3dc517a9c402bdbfc9a0c0f721f9d53faf4aafdc4b8f7a1b580fcaa52338d4bd95f58966a243cdcd3f446ed4bc546d9f607b190dd69954450d16cd0e2d6437067d8b44d19a6af7a7cfa8794e5fbd728e8fb2f2e8db5dd4ff1aa275f35886098e80ff844886060da8b1e7137846b23b"
+    ],
+    -- COUNT = 1
+    [ "8df013b4d103523073917ddf6a869793059e9943fc8654549e7ab22f7c29f122"
+    , "da2625af2ddd4abcce3cf4fa4659d84e"
+    , "b571e66d7c338bc07b76ad3757bb2f9452bf7e07437ae8581ce7bc7c3ac651a9"
+    , ""
+    , ""
+    , "b91cba4cc84fa25df8610b81b641402768a2097234932e37d590b1154cbd23f97452e310e291c45146147f0da2d81761fe90fba64f94419c0f662b28c1ed94da487bb7e73eec798fbcf981b791d1be4f177a8907aa3c401643a5b62b87b89d66b3a60e40d4a8e4e9d82af6d2700e6f535cdb51f75c321729103741030ccc3a56"
+    ],
+    -- COUNT = 2
+    [ "565b2b77937ba46536b0f693b3d5e4a8a24563f9ef1f676e8b5b2ef17823832f"
+    , "4ef3064ec29f5b7f9686d75a23d170e3"
+    , "3b722433226c9dba745087270ab3af2c909425ba6d39f5ce46f07256068319d9"
+    , ""
+    , ""
+    , "d144ee7f8363d128872f82c15663fe658413cd42651098e0a7c51a970de75287ec943f9061e902280a5a9e183a7817a44222d198fbfab184881431b4adf35d3d1019da5a90b3696b2349c8fba15a56d0f9d010a88e3f9eeedb67a69bcaa71281b41afa11af576b765e66858f0eb2e4ec4081609ec81da81df0a0eb06787340ea"
+    ],
+    -- COUNT = 3
+    [ "fc3832a91b1dcdcaa944f2d93cbceb85c267c491b7b59d017cde4add79a836b6"
+    , "d5e76ce9eabafed06e33a913e395c5e0"
+    , "ffc5f6eefd51da64a0f67b5f0cf60d7ab43fc7836bca650022a0cee57a43c148"
+    , ""
+    , ""
+    , "0e713c6cc9a4dbd4249201d12b7bf5c69c3e18eb504bf3252db2f43675e17d99b6a908400cea304011c2e54166dae1f20260008efe4e06a87e0ce525ca482bca223a902a14adcf2374a739a5dfeaf14cadd72efa4d55d15154c974d9521535bcb70658c5b6c944020afb04a87b223b4b8e5d89821704a9985bb010405ba8f3d4"
+    ],
+    -- COUNT = 4
+    [ "8009eb2cb49fdf16403bcdfd4a9f952191062acb9cc111eca019f957fb9f4451"
+    , "355598866952394b1eddd85d59f81c9d"
+    , "09ff1d4b97d83b223d002e05f754be480d13ba968e5aac306d71cc9fc49cc2dd"
+    , ""
+    , ""
+    , "9550903c2f02cf77c8f9c9a37041d0040ee1e3ef65ba1a1fbbcf44fb7a2172bd6b3aaabe850281c3a1778277bacd09614dfefececac64338ae24a1bf150cbf9d9541173a82ecba08aa19b75abb779eb10efa4257d5252e8afcac414bc3bb5d3006b6f36fb9daea4c8c359ef6cdbeff27c1068571dd3c89dc87eda9190086888d"
+    ],
+    -- COUNT = 5
+    [ "a6e4c9a8bd6da23b9c2b10a7748fd08c4f782fadbac7ea501c17efdc6f6087bd"
+    , "acdc47edf1d3b21d0aec7631abb6d7d5"
+    , "c16ee0908a5886dccf332fbc61de9ec7b7972d2c4c83c477409ce8a15c623294"
+    , ""
+    , ""
+    , "a52f93ccb363e2bdf0903622c3caedb7cffd04b726052b8d455744c71b76dee1b71db9880dc3c21850489cb29e412d7d80849cfa9151a151dcbf32a32b4a54cac01d3200200ed66a3a5e5c131a49655ffbf1a8824ff7f265690dffb4054df46a707b9213924c631c5bce379944c856c4f7846e281ac89c64fad3a49909dfb92b"
+    ],
+    -- COUNT = 6
+    [ "59d6307460a9bdd392dfc0904973991d585696010a71e52d590a5039b4849fa4"
+    , "34a0aafb95917cbf8c38fc5548373c05"
+    , "0407b7c57bc11361747c3d67526c36e228028a5d0b145d66ab9a2fe4b07507a0"
+    , ""
+    , ""
+    , "299aba0661315211b09d2861855d0b4b125ab24649461341af6abd903ed6f025223b3299f2126fcad44c675166d800619cf49540946b12138989417904324b0ddad121327211a297f11259c9c34ce4c70c322a653675f78d385e4e2443f8058d141195e17e0bd1b9d44bf3e48c376e6eb44ef020b11cf03eb141c46ecb43cf3d"
+    ],
+    -- COUNT = 7
+    [ "9ae3506aadbc8358696ba1ba17e876e1157b7048235921503d36d9211b430342"
+    , "9abf7d66afee5d2b811cba358bbc527d"
+    , "0d645f6238e9ceb038e4af9772426ca110c5be052f8673b8b5a65c4e53d2f519"
+    , ""
+    , ""
+    , "5f032c7fec6320fe423b6f38085cbad59d826085afe915247b3d546c4c6b174554dd4877c0d671de9554b505393a44e71f209b70f991ac8aa6e08f983fff2a4c817b0cd26c12b2c929378506489a75b2025b358cb5d0400821e7e252ac6376cd94a40c911a7ed8b6087e3de5fa39fa6b314c3ba1c593b864ce4ff281a97c325b"
+    ],
+    -- COUNT = 8
+    [ "96ae3b8775b36da2a29b889ad878941f43c7d51295d47440cd0e3c4999193109"
+    , "1fe022a6fc0237b055d4d6a7036b18d5"
+    , "1e40e97362d0a823d3964c26b81ab53825c56446c5261689011886f19b08e5c2"
+    , ""
+    , ""
+    , "e707cd14b06ce1e6dbcceaedbf08d88891b03f44ad6a797bd12fdeb557d0151df9346a028dec004844ca46adec3051dafb345895fa9f4604d8a13c8ff66ae093fa63c4d9c0816d55a0066d31e8404c841e87b6b2c7b5ae9d7afb6840c2f7b441bf2d3d8bd3f40349c1c014347c1979213c76103e0bece26ad7720601eff42275"
+    ],
+    -- COUNT = 9
+    [ "33f5120396336e51ee3b0b619b5f873db05ca57cda86aeae2964f51480d14992"
+    , "6f1f6e9807ba5393edcf3cb4e4bb6113"
+    , "3709605af44d90196867c927512aa8ba31837063337b4879408d91a05c8efa9f"
+    , ""
+    , ""
+    , "8b8291126ded9acef12516025c99ccce225d844308b584b872c903c7bc6467599a1cead003dc4c70f6d519f5b51ce0da57f53da90dbe8f666a1a1dde297727fee2d44cebd1301fc1ca75956a3fcae0d374e0df6009b668fd21638d2b733e6902d22d5bfb4af1b455975e08eef0ebe4dc87705801e7776583c8de11672729f723"
+    ],
+    -- COUNT = 10
+    [ "ad300b799005f290fee7f930eebce158b98fb6cb449987fe433f955456b35300"
+    , "06aa2514e4bd114edf7ac105cfef2772"
+    , "87ada711465e4169da2a74c931afb9b5a5b190d07b7af342aa99570401c3ee8a"
+    , ""
+    , ""
+    , "80d7c606ff49415a3a92ba1f2943235c01339c8f9cd0b0511fbfdf3ef23c42ffff008524193faaa4b7f2f2eb0cfa221d9df89bd373fe4e158ec06fad3ecf1eb48b8239b0bb826ee69d773883a3e8edac66254610ff70b6609836860e39ea1f3bfa04596fee1f2baca6cebb244774c6c3eb4af1f02899eba8f4188f91776de16f"
+    ],
+    -- COUNT = 11
+    [ "130b044e2c15ab89375e54b72e7baae6d4cad734b013a090f4df057e634f6ff0"
+    , "65fd6ac602cd44107d705dbc066e52b6"
+    , "f374aba16f34d54aae5e494505b67d3818ef1c08ea24967a76876d4361379aec"
+    , ""
+    , ""
+    , "5d179534fb0dba3526993ed8e27ec9f915183d967336bb24352c67f4ab5d7935d3168e57008da851515efbaecb69904b6d899d3bfa6e9805659aef2942c4903875b8fcbc0d1d24d1c075f0ff667c1fc240d8b410dff582fa71fa30878955ce2ed786ef32ef852706e62439b69921f26e84e0f54f62b938f04905f05fcd7c2204"
+    ],
+    -- COUNT = 12
+    [ "716430e999964b35459c17921fe5f60e09bd9ab234cb8f4ba4932bec4a60a1d5"
+    , "9533b711e061b07d505da707cafbca03"
+    , "372ae616d1a1fc45c5aecad0939c49b9e01c93bfb40c835eebd837af747f079d"
+    , ""
+    , ""
+    , "a80d6a1b2d0ce01fe0d26e70fb73da20d45841cf01bfbd50b90d2751a46114c0e758cb787d281a0a9cf62f5c8ce2ee7ca74fefff330efe74926acca6d6f0646e4e3c1a1e52fce1d57b88beda4a5815896f25f38a652cc240deb582921c8b1d03a1da966dd04c2e7eee274df2cd1837096b9f7a0d89a82434076bc30173229a60"
+    ],
+    -- COUNT = 13
+    [ "7679f154296e6d580854826539003a82d1c54e2e062c619d00da6c6ac820789b"
+    , "55d12941b0896462e7d888e5322a99a3"
+    , "ba4d1ed696f58ef64596c76cee87cc1ca83069a79e7982b9a06f9d62f4209faf"
+    , ""
+    , ""
+    , "10dc7cd2bb68c2c28f76d1b04ae2aa287071e04c3b688e1986b05cc1209f691daa55868ebb05b633c75a40a32b49663185fe5bb8f906008347ef51590530948b87613920014802e5864e0758f012e1eae31f0c4c031ef823aecfb2f8a73aaa946fc507037f9050b277bdeaa023123f9d22da1606e82cb7e56de34bf009eccb46"
+    ],
+    -- COUNT = 14
+    [ "8ca4a964e1ff68753db86753d09222e09b888b500be46f2a3830afa9172a1d6d"
+    , "a59394e0af764e2f21cf751f623ffa6c"
+    , "eb8164b3bf6c1750a8de8528af16cffdf400856d82260acd5958894a98afeed5"
+    , ""
+    , ""
+    , "fc5701b508f0264f4fdb88414768e1afb0a5b445400dcfdeddd0eba67b4fea8c056d79a69fd050759fb3d626b29adb8438326fd583f1ba0475ce7707bd294ab01743d077605866425b1cbd0f6c7bba972b30fbe9fce0a719b044fcc1394354895a9f8304a2b5101909808ddfdf66df6237142b6566588e4e1e8949b90c27fc1f"
+    ]
+    ]
+
+{-
+    [SHA-256]
+    [PredictionResistance = False]
+    [EntropyInputLen = 256]
+    [NonceLen = 128]
+    [PersonalizationStringLen = 256]
+    [AdditionalInputLen = 256]
+    [ReturnedBitsLen = 1024]
+-}
+
+t4 :: [TestVector]
+t4 =
+    [
+    -- COUNT = 0
+    [ "5d3286bc53a258a53ba781e2c4dcd79a790e43bbe0e89fb3eed39086be34174b"
+    , "c5422294b7318952ace7055ab7570abf"
+    , "2dba094d008e150d51c4135bb2f03dcde9cbf3468a12908a1b025c120c985b9d"
+    , "793a7ef8f6f0482beac542bb785c10f8b7b406a4de92667ab168ecc2cf7573c6"
+    , "2238cdb4e23d629fe0c2a83dd8d5144ce1a6229ef41dabe2a99ff722e510b530"
+    , "d04678198ae7e1aeb435b45291458ffde0891560748b43330eaf866b5a6385e74c6fa5a5a44bdb284d436e98d244018d6acedcdfa2e9f499d8089e4db86ae89a6ab2d19cb705e2f048f97fb597f04106a1fa6a1416ad3d859118e079a0c319eb95686f4cbcce3b5101c7a0b010ef029c4ef6d06cdfac97efb9773891688c37cf"
+    ],
+    -- COUNT = 1
+    [ "c2a566a9a1817b15c5c3b778177ac87c24e797be0a845f11c2fe399dd37732f2"
+    , "cb1894eb2b97b3c56e628329516f86ec"
+    , "13ce4d8dd2db9796f94156c8e8f0769b0aa1c82c1323b61536603bca37c9ee29"
+    , "413dd83fe56835abd478cb9693d67635901c40239a266462d3133b83e49c820b"
+    , "d5c4a71f9d6d95a1bedf0bd2247c277d1f84a4e57a4a8825b82a2d097de63ef1"
+    , "b3a3698d777699a0dd9fa3f0a9fa57832d3cefac5df24437c6d73a0fe41040f1729038aef1e926352ea59de120bfb7b073183a34106efed6278ff8ad844ba0448115dfddf3319a82de6bb11d80bd871a9acd35c73645e1270fb9fe4fa88ec0e465409ea0cba809fe2f45e04943a2e396bbb7dd2f4e0795303524cc9cc5ea54a1"
+    ],
+    -- COUNT = 2
+    [ "a33288a96f41dd54b945e060c8bd0c094f1e28267cc1dcbba52063c1a9d54c4d"
+    , "36918c977e1a7276a2bb475591c367b7"
+    , "6aa528c940962638dc2201738850fd1fe6f5d0eb9f687ff1af39d9c7b36830d9"
+    , "37ee633a635e43af59abdb1762c7ea45bfe060ec1d9077ecd2a43a658673f3c7"
+    , "2eb96f2e28fa9f674bb03ade703b8f791ee5356e2ee85c7ed5bda96325256c61"
+    , "db2f91932767eb846961ce5321c7003431870508e8c6f8d432ca1f9cee5cdc1aed6e0f133d317eb6990c4b3b0a360cdfb5b43a6e712bd46bca04c414868fab22c6a49c4b89c812697c3a7fbfc8ddf10c8aa5ebf13a09fd114eb2a02a07f69786f3ce7fd30231f22779bc8db103b13fa546dbc45a89a86275281172761683d384"
+    ],
+    -- COUNT = 3
+    [ "5f37b6e47e1776e735adc03d4b999879477ff4a206231924033d94c0114f911b"
+    , "7d12d62c79c9f6234ae0314156947459"
+    , "92d4d9fab5f8bf5119f2663a9df7334f50dcde74fb9d7732f7eba56501e60d54"
+    , "c9aef0d7a9ba7345d08b6d5b5ce5645c7495b8685e6b93846ffcf470f5abd40d"
+    , "50d9d1f5074f7d9f1a24a9c63aa47b94da5ba78db1b0f18e4d4fe45c6875813c"
+    , "20d942bbd7d98700faa37e94d53bf74f2d6bd1d8c95c0b88d842c4857797d59e7c8788aeeac29740122f208f703bf35dc32b0035db0648384feb6aa17a3274bc09b2d2b746c5a06fd82f4469fb86131a49482cb7be7d9b4b95042394cfb18b13f333ec0fe5c227bf1d8f33ecb2e42e358b6c3e034cb585331bd1d27f638029b9"
+    ],
+    -- COUNT = 4
+    [ "2311c5afd64c584484b2729e84db80c0b4063fe9ca7edc83350488d7e67264a0"
+    , "6a6dfd975a0dc7b72df1f107c4b3b3a6"
+    , "2abd870ec5fe26ed14dfa57a3309f920131b70580c3639af2645cd1af93db1b1"
+    , "c6e532a3b25653b6002aed5269cc2118749306e736bde039d4d569d4f967773f"
+    , "5e7d26c4da769c373092b2b4f72b109fe34bdb7d169ea38f78ebae5df4a15759"
+    , "cacaeb1b4ac2305d8714eb50cbe1c67c5a2c0bbc7938fdfdcafef7c85fc40becbf777a4cfb6f14c6eee320943a493d2b0a744a6eb3c256ee9a3763037437df9adce3e2260f0c35e958af0edb5a81debd8bdaf2b8bb2b98b9186e5a222a21609ff58df4cbe1d4898d10d6e7c46f31f5cb1041bfd83a5fb27d5c56c961e91403fc"
+    ],
+    -- COUNT = 5
+    [ "362ece9d330e1172a8f9e50258476d0c79c3ee50346524ba12d970ee3a6ef8c5"
+    , "cf11bcb4d9d51311ceacfca8705e833f"
+    , "abb5a8edde02e526449284ecc31bc713383df3ed085f752e3b6a32f305861eed"
+    , "746302ab1f4a86b17546bea762e929360f2e95c7788a63545a264ef997c8c65e"
+    , "b907c5b2a8833a48e56e819228ce9a050b41b3309f5ca37bed720311d92b33af"
+    , "73c7131a558350590053580873ef956ff952f2aa6ff1bea452e013d1bc2afddea2311756dbe756e63ba6258480c48f3f6c1319b5f572f67ca530af09e39413d1d432bea8f89206619618cb0e7c88e9f2033639d0eb0efc20616b64f940da99b88231984c3fb23f19e890576f555fde394dbd4351f17a7ffd5c369379001bda03"
+    ],
+    -- COUNT = 6
+    [ "cf614bc29946bc0095f415e8bdeda10aab05392f9cc9187a86ea6ec95ee422e1"
+    , "77fb5ec22dc0432cc13f4693e2e3bd9a"
+    , "e4ce77914ffbc5fddf1fb51edfafdc196109139b84c741354135ec8d314c7c43"
+    , "e1e83ee1205acaf6164dc287aec08e5b32789e5be818078db39e53cad589db51"
+    , "4e20c0226d5e1e7e805679f03f72452b5bea2d0ba41e0c12329bf60eb3016dd1"
+    , "838fdf1418a746aa52ae4005d90c3fd301f648c5770ffef2a9f3912e37a93850cc4b8bfcce910aead0cb75958823b1a62e283901c5e4a3980e4ea36257458e2e4953555819b8852a26489b1d74821f80c9908469b43f124ff7ea62497c36159a47353098a1b9ec32e54800d6704371cc37f357ad74aacc203e9b6db97f94d0c4"
+    ],
+    -- COUNT = 7
+    [ "a8da1d3e233f393fd44d204c200202f7d01896e72c5ac652940cfd15b5d4b0bd"
+    , "0a112b4cb0890af0a495e0f49fcf6874"
+    , "d2e32799bc822b8d033299bdf63dc35774f7649e935d25be5b10512c430d1bda"
+    , "920a82d76fcd2cd106ada64bba232b7b2344f3afe6b1d1d20ee8795144571009"
+    , "eeaac5878275372025f8231febed64db6a11273c3c00d625fc80a95f18ad7d3f"
+    , "5f6dae489b53d89027b2cc333c700f090152d77b3eaf01d47f56ce6eca9893ef877b4cb560fab0fbdb34e3d1c6cd8480b33c053d2661a10aa531df4961b97d659c7492584236582b3fe701055efa59c328194cd1e07fcffd910d9ee01b7b9e8c8fda7f7ac01a8e203b8b26eb8078a9b9a5021562c44af24089e3ef84c1d5a6bd"
+    ],
+    -- COUNT = 8
+    [ "a77b1ed4ecaa650374e1052c405f1d88881c25c87d13dbe1334d8c1a847fa76b"
+    , "05c143e2f145db216fe7be9ed23635d0"
+    , "b5c750968ff09ed251d4a1c05342ac843db5246b19045728a634fa4f6e752e54"
+    , "ff5937bcd01a363696bf8e40adc8e4ab3e56dbf7e7d09451c99e538785fe6697"
+    , "4acb34eea8266badcf8f6557a0eecf3eb4d7a295c876d6175598cb66a388efb8"
+    , "ec13eadfcc84e77d2a2efa1a2cd8b1355587cb27feb3d19d75b37f0446333ddb8236e751c63b7a6e595ec24a25051a696dbe8c062dd8896d1446db228a2f10e8094ee07e7ee648ed6bebb2f5ec5aae24c9c640665c28355cc11c116795ecc070790f7fdfc4398900311b6695d5da0175091ed1828d2731085bfb4a20bd86cce0"
+    ],
+    -- COUNT = 9
+    [ "491686c781e83eb4e21d9989e8d718100b0d21a2c56295888baef1a65f219651"
+    , "499085296d21065feabf3106101c8d6f"
+    , "d208a72f9ae34f0817669fb04f49239dd31700f3dc9a93db8d75fb79f9b686c1"
+    , "9ffc61893a293a864008fdd56d3292600d9e2ec8a1ea8f34ac5931e968905a23"
+    , "4ff3a397dfdae0912032a302a5e7a07dceca8d9013a21545689319b7c024cd07"
+    , "3c258ebf2203fca3b322ad1b016e21c7f5c148425f81e4fb0a0e462dce9dfa569c37a006527768297a5b68461b08912642a341b88c85597e30e7561206886098c4e2d861f11513f0ffdbbc78d3a2dd60c105abbb33c5e05ae27081b690fb8b3610917aa9bf1a4ad74481b5ff8334f14e5ad6a6a1eb2259476078076fb7e3a992"
+    ],
+    -- COUNT = 10
+    [ "36a5267eeeb5a1a7d46de0f8f9281f73cd9611f01198fdaa78c5315205e5a177"
+    , "b66b5337970df36219321badacc624eb"
+    , "c2a7b164949da102bece44a423197682ff97627d1fe9654266b8527f64e5b386"
+    , "a977e2d8637b019c74063d163bb25387dc56f4eb40e502cefc5ae6ad26a6abdc"
+    , "c5c9819557b1e7d8a86fa8c60be42993edc3ef539c13d9a51fb64b0de06e145e"
+    , "b471711a4fc7ab7247e65d2c2fe49a50169187187b7978cd2fdb0f8318be3ec55fc68ed4577ad9b42cbb57100b5d35ac86c244c4c93a5b28c1a11c2dfe905d608ec7804dec5bb15cf8d79695534d5e13a6a7e18a887ec9cf184da0cbbc6267f3a952a769403bafcdbb559401be0d8b3300ea7258b4026fc892175efd55ba1a67"
+    ],
+    -- COUNT = 11
+    [ "a76b0366df89e4073a6b6b9c04da1d6817ce26f1c4825cad4097bdf4d7b9445e"
+    , "773d3cc3290176773847869be528d1a4"
+    , "1bfd3bcfb9287a5ad055d1b2b8615fa81c94ac24bc1c219a0f8de58789e0404a"
+    , "edd879fa56f21d93029da875b683ce50f6fdc4c0da41da051d000eed2afefefa"
+    , "f528ffd29160039260133ed9654589ce60e39e7f667c34f82cda65ddcf5fff14"
+    , "39d1ff8848e74dd2cdc6b818ad69823878062116fdf1679942f892c7e191be1c4b6ea268ecdff001b22af0d510f30c2c25b90fc34927f46e3f45d36b0e1848b3a5d54c36c7c65ee7287d325dfbb51b56a438feb6650ce13df88bf06b87ac4a35d2a199ea888629fb0d83f82f0ea160dc79ed220d8ef195b9e80c542f60c2d320"
+    ],
+    -- COUNT = 12
+    [ "46571e1df43e5e141235e2a9ec85bb0faf1dc0566031e14d41a2fbd0315653ec"
+    , "b60ef6a3347967519aabeaf748e4e991"
+    , "759fd8593e3688b23c4a003b655311770d670789878570eb3b155a8e6c2d8c45"
+    , "033128460b449e1accb0e9c54508759ddc2538bc64b51e6277553f0c60a02723"
+    , "a5e4a717240bdeac18a0c0e231a11dc04a47d7550f342fa9a7a5ff334eb9327d"
+    , "9d222df1d530ea7f8f2297a0c79d637da570b48042ecddded75956bba0f0e70b271ffa3c9a53bada6ee1b8a4203c22bfde82a5e2eb1b150f54c6483458569422c1a34a8997d42cc09750167a78bf52a0bd158397af9f83caabe689185c099bf0a9a4853dd3cf8b8e89efebb6a27dba873e65e9927741b22968f2875789b44e01"
+    ],
+    -- COUNT = 13
+    [ "d63980e63bbe4ac08d2ac5646bf085b82c75995e3fdfc23bb9cc734cd85ca7d2"
+    , "d33ed1dcae13fb634ba08272d6697590"
+    , "acd0da070072a5340c4f5f4395568e1a36374e074196ae87f3692ee40487e1df"
+    , "f567677b5e12e26f3544be3da9314c88fc475bf84804a89a51f12b191392c02b"
+    , "c01cc7873e93c86e2bfb8fc984cfc2eab5cc58eeef018fedb5cba5aedd386156"
+    , "b133446f633bcb40724bbf9fa187c39a44b9c094a0a0d40e98977e5466dc2c9adf62a5f4551eeb6406a14658de8a0ed7487c3bf6277e811101284a941745ce16176acc875f1435e14161772fa84609e8123c53dd03cbb868030835c0d11d8d6aa04a1b6f908248b028997737f54735ec4ed7a81fc868199ffb61a779d9340334"
+    ],
+    -- COUNT = 14
+    [ "3d99f9b7ac3a2fbe9cf15d960bf41f5588fc4db1e0d2a5c9c0fe9059f03593fb"
+    , "411f504bb63a9b3afa7ffa1357bb48be"
+    , "0bb5ebd55981a25ba69164da49fa92f2871fd3fc65eb30d0f0d0b8d798a4f8f2"
+    , "288e948a551284eb3cb23e26299955c2fb8f063c132a92683c1615ecaed80f30"
+    , "d975b22f79e34acf5db25a2a167ef60a10682dd9964e15533d75f7fa9efc5dcb"
+    , "ee8d707eea9bc7080d58768c8c64a991606bb808600cafab834db8bc884f866941b4a7eb8d0334d876c0f1151bccc7ce8970593dad0c1809075ce6dbca54c4d4667227331eeac97f83ccb76901762f153c5e8562a8ccf12c8a1f2f480ec6f1975ac097a49770219107d4edea54fb5ee23a8403874929d073d7ef0526a647011a"
+    ]
+    ]
+
+{- Reseed test vectors -}
+
+{-
+    [SHA-256]
+    [PredictionResistance = False]
+    [EntropyInputLen = 256]
+    [NonceLen = 128]
+    [PersonalizationStringLen = 0]
+    [AdditionalInputLen = 0]
+    [ReturnedBitsLen = 1024]
+-}
+
+r1 :: [TestVector]
+r1 =
+    [
+    -- COUNT = 0
+    [ "06032cd5eed33f39265f49ecb142c511da9aff2af71203bffaf34a9ca5bd9c0d"
+    , "0e66f71edc43e42a45ad3c6fc6cdc4df"
+    , ""
+    , "01920a4e669ed3a85ae8a33b35a74ad7fb2a6bb4cf395ce00334a9c9a5a5d552"
+    , ""
+    , ""
+    , ""
+    , "76fc79fe9b50beccc991a11b5635783a83536add03c157fb30645e611c2898bb2b1bc215000209208cd506cb28da2a51bdb03826aaf2bd2335d576d519160842e7158ad0949d1a9ec3e66ea1b1a064b005de914eac2e9d4f2d72a8616a80225422918250ff66a41bd2f864a6a38cc5b6499dc43f7f2bd09e1e0f8f5885935124"
+    ],
+    -- COUNT = 1
+    [ "aadcf337788bb8ac01976640726bc51635d417777fe6939eded9ccc8a378c76a"
+    , "9ccc9d80c89ac55a8cfe0f99942f5a4d"
+    , ""
+    , "03a57792547e0c98ea1776e4ba80c007346296a56a270a35fd9ea2845c7e81e2"
+    , ""
+    , ""
+    , ""
+    , "17d09f40a43771f4a2f0db327df637dea972bfff30c98ebc8842dc7a9e3d681c61902f71bffaf5093607fbfba9674a70d048e562ee88f027f630a78522ec6f706bb44ae130e05c8d7eac668bf6980d99b4c0242946452399cb032cc6f9fd96284709bd2fa565b9eb9f2004be6c9ea9ff9128c3f93b60dc30c5fc8587a10de68c"
+    ],
+    -- COUNT = 2
+    [ "62cda441dd802c7652c00b99cac3652a64fc75388dc9adcf763530ac31df9214"
+    , "5fdc897a0c1c482204ef07e0805c014b"
+    , ""
+    , "bd9bbf717467bf4b5db2aa344dd0d90997c8201b2265f4451270128f5ac05a1a"
+    , ""
+    , ""
+    , ""
+    , "7e41f9647a5e6750eb8acf13a02f23f3be77611e51992cedb6602c314531aff2a6e4c557da0777d4e85faefcb143f1a92e0dbac8de8b885ced62a124f0b10620f1409ae87e228994b830eca638ccdceedd3fcd07d024b646704f44d5d9c4c3a7b705f37104b45b9cfc2d933ae43c12f53e3e6f798c51be5f640115d45cf919a4"
+    ],
+    -- COUNT = 3
+    [ "6bdc6ca8eef0e3533abd02580ebbc8a92f382c5b1c8e3eaa12566ecfb90389a3"
+    , "8f8481cc7735827477e0e4acb7f4a0fa"
+    , ""
+    , "72eca6f1560720e6bd1ff0152c12eeff1f959462fd62c72b7dde96abcb7f79fb"
+    , ""
+    , ""
+    , ""
+    , "d5a2e2f254b5ae65590d4fd1ff5c758e425be4bacdeede7989669f0a22d34274fdfc2bf87135e30abdae2691629c2f6f425bd4e119904d4785ecd9328f15259563e5a71f915ec0c02b66655471067b01016fdf934a47b017e07c21332641400bbe5719050dba22c020b9b2d2cdb933dbc70f76fec4b1d83980fd1a13c4565836"
+    ],
+    -- COUNT = 4
+    [ "096ef37294d369face1add3eb8b425895e921626495705c5a03ee566b34158ec"
+    , "6e2e0825534d2989715cc85956e0148d"
+    , ""
+    , "1b4f7125f472c253837fa787d5acf0382a3b89c3f41c211d263052402dcc62c5"
+    , ""
+    , ""
+    , ""
+    , "4541f24f759b5f2ac2b57b51125077cc740b3859a719a9bab1196e6c0ca2bd057af9d3892386a1813fc8875d8d364f15e7fd69d1cc6659470415278164df656295ba9cfcee79f6cbe26ee136e6b45ec224ad379c6079b10a2e0cb5f7f785ef0ab7a7c3fcd9cb6506054d20e2f3ec610cbba9b045a248af56e4f6d3f0c8d96a23"
+    ],
+    -- COUNT = 5
+    [ "a7dccdd431ae5726b83585b54eae4108f7b7a25c70187c0acbb94c96cc277aa8"
+    , "94c8f4b8e195a47356a89a50d1389ab5"
+    , ""
+    , "51733eee2e922f4055e53939e222e71fae730eb037443db2c7679708abb86a65"
+    , ""
+    , ""
+    , ""
+    , "99ba2691a622afecc9472418e6a8f9f1cdc1e3583c3bc7a2a650a1ab79dcbccbd656636c573179276e782569420c97438c06be898867f628b1c01eb570263d2c0f09c7aab536f6fba7df6aad19e05c236b645674667c03d1b6a04d7fc11177fe78933b309679f5bf26a4632b9a13e314c4bf4532428d3d95c689002b6dc1fbb1"
+    ],
+    -- COUNT = 6
+    [ "c286425ecf543a49bcc9196b0db1a80bc54e4948adba6f41712a350a02891fa6"
+    , "957a659a4ec2e0b7ad185483c220fd61"
+    , ""
+    , "08c2129813eea0776fba72788fdf2718759cc3c4207fa20a5fe23ac6e32cc28e"
+    , ""
+    , ""
+    , ""
+    , "8e1020a4fd84c99e0fc7e3f7ce48de5ed9ec9a5c2ccd624dbe6f30e2f688a31dc55957630357a5d48ca2a456241a28bfb16d8bb000877697a7ce24d9ad4d22b0c15117996f1f270b94f46d7a9bdfa7608fa1dd849177a9b8049e51b6b7a2742623854a1fddb5efc447eed1ea1aed6f02b4b2754ecf71ea0509da2e54f524a7e7"
+    ],
+    -- COUNT = 7
+    [ "02818bd7c1ec456ace55beeba99f646a6d3aa0ea78356ea726b763ff0dd2d656"
+    , "c482687d508c9b5c2a75f7ce390014e8"
+    , ""
+    , "cf319bfa63980e3cb997fd28771bb5614e3acb1149ba45c133ffbbab17433193"
+    , ""
+    , ""
+    , ""
+    , "19a231ff26c1865ce75d7a7185c30dd0b333126433d0c8cbf1be0d2b384d4eb3a8aff03540fbfa5f5496521a4e4a64071b44c78bd0b7e68fac9e5695c5c13fd3b9dbe7f7739781a4c8f0b980f1b17d99bce17ceb52b56866ae02456ffef83399c8cf7826f3c45c8a19315890919d20f40fc4e18d07e9c8ccd16c3327b5988f71"
+    ],
+    -- COUNT = 8
+    [ "77a5c86d99be7bc2502870f4025f9f7563e9174ec67c5f481f21fcf2b41cae4b"
+    , "ed044ad72ee822506a6d0b1211502967"
+    , ""
+    , "778100749f01a4d35c3b4a958aafe296877e0acafd089f50bc7797a42a33ab71"
+    , ""
+    , ""
+    , ""
+    , "831a4da566f46289904893ef1cc1cd4ad19ee48f3857e2b69e936d10afbdc29822e85d02663d346ef3e09a848b1d9cc04f4c4c6e3b3b0e56a034e2334d34ca08f8097be307ba41d020bc94f8c1937fe85644eeb5592c2b5a2138f7ded9a5b44b200c8b5beb27597c790f94d660eb61e8248391edc3ae2d77656cbe8354275b13"
+    ],
+    -- COUNT = 9
+    [ "0ea458cff8bfd1dd8b1addcba9c01317d53039e533104e32f96e7d342e6c7b9b"
+    , "935a4b66fc74c2a48757a99c399e64e3"
+    , ""
+    , "6c5f3708e7b714c4ed139b4fa9e8c763af01773484005109a85e33653bb0ce98"
+    , ""
+    , ""
+    , ""
+    , "373a37af84fddec13645a9768d6a785ae5a2589d64cd9b37980dde2541499210c4f408335de1d585349064f3f53a2b4c5ec6dc2a09591f99ad9fad528ac83474164b45497bf167f81e66fa08463ffea917f6891e48f149fafc20622bb1172f34886feb45c26fd446a4a4e2891b4bc594186896141aaaeeb301b49e7c1a26fec7"
+    ],
+    -- COUNT = 10
+    [ "bfb68be4ce1756d25bdfad5e0c2f8bec29360901cc4da51d423d1591cc57e1ba"
+    , "98afe4bd194c143e099680c504cceaab"
+    , ""
+    , "b97caf210e82498c3408790d41c320dd4a72007778389b44b7bc3c1c4b8c53f8"
+    , ""
+    , ""
+    , ""
+    , "409e0aa949fb3b38231bf8732e7959e943a338ea399026b744df15cbfeff8d71b3da023dcce059a88cf0d4b7475f628e4764c8bef13c70cfbbbb6da2a18aabcad919db09d04fc59765edb165147c88dd473a0f3c5ee19237ca955697e001ba654c5ee0bd26761b49333154426bc63286298a8be634fe0d72cfdeef0f3fc48eca"
+    ],
+    -- COUNT = 11
+    [ "4f6880a64610004463031d67d7924fa446c39138d4d41007e8df3d65691a9367"
+    , "6b33b2c13600f4b1df6ca3d1960e8dd4"
+    , ""
+    , "57b87b8c8f48312b5333d43b367730c0a5ad4725a16778fcb53fe136d136cbfd"
+    , ""
+    , ""
+    , ""
+    , "73d0f324ed186e2ad06bd1800e262bdbda79ba54e626761bd60f74f43e3bb62958ec1e2f1d940af163e1cadc124e7ebaba2f72e67efd746c7f6d0cad53ef03d859d93cff778a32ee5be172fe7fdbdc232ded360d704a6fa0f70bebe942e56478345492f49dc5c6fc346b88a58947ad250e688e8c626fe1efe7624620e571976e"
+    ],
+    -- COUNT = 12
+    [ "aae352e111843219cae8f70e7b8f6eb9bb53d246cbec1e4f07d42757143295b4"
+    , "b84485dccd1bf93210e322eafcbebcd9"
+    , ""
+    , "f9237f00d744d8fbff21b9d0043c258e8731817e6a5fb7b4bf5011680e5bc642"
+    , ""
+    , ""
+    , ""
+    , "cfb28b93522c7d61d8d3ce3f080e435e4c83c7e13a9dab788db8fef0407267a14fbc9324e090e24df5491fedfa81116869983938d4d4d7324a310c3af33a6f7938f602c5e4e63f1771cdaabdab0782b5affb54eb53047c109a9606739dd0065bd21eca33132986554878354f5f9f852e674dd690163b0ff74c7a25e6bae8ce39"
+    ],
+    -- COUNT = 13
+    [ "589e79e339b7d2a1b879f0b0e1a7d1ad2474eaa8025b070f1ffa877b7124d4ff"
+    , "0961ed64dbd62065d96e75de6d2ff9d6"
+    , ""
+    , "e928388d3af48c2968527a4d2f9c2626fbc3f3f5a5d84e0583ab6f78e7f8b081"
+    , ""
+    , ""
+    , ""
+    , "fce6ced1ecf474d181ab331f79c3d2cc8a768ec2818de5b3fc7cf418322716d6a6853733561a497c0c25cb288d2c9fcfbca891bafd5a834c85f3603f402acf1a7b1ea92db847ed5c252a862ad4ab5e259715f1fc81da67f5230bf8be50ee8069758095f7d0e559e03f2c6072290e61794458437609e473eb66580cddaad19b71"
+    ],
+    -- COUNT = 14
+    [ "714277d408ad87fde317f0a94732fce62f1352bdc90936673b4f1daa0925aa26"
+    , "d16582a99f23010b4248b88d86485419"
+    , ""
+    , "bd9fc7cb2fd5063b2c3c0c4f346ad2e3879371a9c805e59b9f2cd2cc2a40894f"
+    , ""
+    , ""
+    , ""
+    , "62ef7a431288252e0d736c1d4e36cc9ac37107dcd0d0e971a22444a4adae73a41eff0b11c8625e118dbc9226142fd0a6aa10ac9b190919bda44e7248d6c88874612abd77fb3716ea515a2d563237c446e2a282e7c3b0a3aef27d3427cc7d0a7d38714659c3401dbc91d3595159318ebca01ae7d7fd1c89f6ad6b604173b0c744"
+    ]
+    ]
+
+{-
+    [SHA-256]
+    [PredictionResistance = False]
+    [EntropyInputLen = 256]
+    [NonceLen = 128]
+    [PersonalizationStringLen = 0]
+    [AdditionalInputLen = 256]
+    [ReturnedBitsLen = 1024]
+-}
+
+r2 :: [TestVector]
+r2 =
+    [
+    -- COUNT = 0
+    [ "05ac9fc4c62a02e3f90840da5616218c6de5743d66b8e0fbf833759c5928b53d"
+    , "2b89a17904922ed8f017a63044848545"
+    , ""
+    , "2791126b8b52ee1fd9392a0a13e0083bed4186dc649b739607ac70ec8dcecf9b"
+    , "43bac13bae715092cf7eb280a2e10a962faf7233c41412f69bc74a35a584e54c"
+    , "3f2fed4b68d506ecefa21f3f5bb907beb0f17dbc30f6ffbba5e5861408c53a1e"
+    , "529030df50f410985fde068df82b935ec23d839cb4b269414c0ede6cffea5b68"
+    , "02ddff5173da2fcffa10215b030d660d61179e61ecc22609b1151a75f1cbcbb4363c3a89299b4b63aca5e581e73c860491010aa35de3337cc6c09ebec8c91a6287586f3a74d9694b462d2720ea2e11bbd02af33adefb4a16e6b370fa0effd57d607547bdcfbb7831f54de7073ad2a7da987a0016a82fa958779a168674b56524"
+    ],
+    -- COUNT = 1
+    [ "1bea3296f24e9242b96ed00648ac6255007c91f7c1a5088b2482c28c834942bf"
+    , "71073136a5cc1eb5b5fa09e1790a0bed"
+    , ""
+    , "d714329f3fbea1df9d0b0b0d88dfe3774beb63d011935923d048e521b710dc6f"
+    , "4ef872fd211a426ea1085ab39eb220cc698fdfeabe49b8835d620ab7885de7a4"
+    , "d74d1669e89875852d9ccbf11c20fe3c13a621ebcb3f7edeea39a2b3379fdcf5"
+    , "0c8aa67ca310bd8e58c16aba35880f747266dbf624e88ec8f9ee9be5d08fdeb1"
+    , "ce95b98f13adcdf7a32aa34709d6e02f658ae498d2ab01ce920f69e7e42c4be1d005acf0ca6b17891dfafc620dd4cd3894f8492a5c846089b9b452483eb0b91f3649ec0b6f98d1aaabc2e42cd39c2b25081b85ab50cb723007a0fd83550f32c210b7c4150b5a6bb3b0c9e3c971a09d43acb48e410a77f824b957092aa8ef98bc"
+    ],
+    -- COUNT = 2
+    [ "a7ea449b49db48601fc3a3d5d77081fab092b8d420ed1b266f704f94352dd726"
+    , "d11a159b60af8d20a0e37d27e6c74aa3"
+    , ""
+    , "50916ab47e8cb5dc843f9fba80639103711f86be8e3aa94f8a64a3fe0e6e5b35"
+    , "e2bb6768120555e7b9e0d573537a82f8f32f54560e1050b6abb1588fb3441e66"
+    , "a50cec9d1ecddb2c163d24019e81c31a2b350ccd3ad8181fd31bb8d1f64fa50e"
+    , "591dbbd48b51abced67f9c6269cf0133cd3dcbb5cfafcb6ef758569c555a5773"
+    , "0a464abcc8685158372d544635b953fcb1d3821c30aaa93982f9b788935f00f88115aad61d5cee003b3d1cb50f3e961a501e2dd0fc7e1724778b184a4bdf9f64e110dda7446e5544a30bd49a400ea1a5411800e1edfeea349323618afc5dc5782dc4b71d2da4d6a4785f8dd346feb9c8740ffd26bf644e3e4323ff24c30b9f10"
+    ],
+    -- COUNT = 3
+    [ "14683ec508a29d7812e0f04a3e9d87897000dc07b4fbcfda58eb7cdabc492e58"
+    , "b2243e744eb980b3ece25ce76383fd46"
+    , ""
+    , "18590e0ef4ee2bdae462f76d9324b3002559f74c370cfccf96a571d6955703a7"
+    , "9ea3ccca1e8d791d22fcda621fc4d51b882df32d94ea8f20ee449313e6909b78"
+    , "16366a578b5ea4d0cb547790ef5b4fd45d7cd845bc8a7c45e99419c8737debb4"
+    , "a68caa29a53f1ba857e484d095805dc319fe6963e4c4daaf355f722eba746b92"
+    , "c4e7532ee816789c2d3da9ff9f4b37139a8515dbf8f9e1d0bf00c12addd79ebbd76236f75f2aa705a09f7955038ebff0d566911c5ea13214e2c2eeb46d23ad86a33b60f7b9448d63eec3e1d59f48b39552857447dc5d7944667a230e3dbfa30ca322f6eacaf7536a286706a627c5083c32de0658b9073857c30fb1d86eb8ad1b"
+    ],
+    -- COUNT = 4
+    [ "fa261fb230e2822458532ca2d5c39758750e6819a6fcebef10579ba995096959"
+    , "564e1c9fbcb12878df2bd49202cbf821"
+    , ""
+    , "bf7de29e99e7f0e1b9f96f3b1902fb4049c8c6234d20de8316ebe66d97725457"
+    , "8b7326621f6afbd44a726de48d03bcc5331f7306026c229ea9523497fbeaa88d"
+    , "33b00b31623d6160c4c6740363a96481be14b19bc47be95641227284c366922a"
+    , "2d812c8203575790ad6b6f2ed91a49d57460de779a3e881bef3be12e8766dc91"
+    , "5574e0b4efc17e8ce136e592beabfe32551072bddd740929e698467b40b3991f028a22c760f7034853cc53007e3793e3c4a600d9e9d94528f8dc09aeba86146cdde2b7f71255ae0efc529b49be2205979dba6525bfe155e8819e8e2aeeaa285704242da90b4c4535101cc47d94b0e388a1b2e63ad0cbe158b9e1bbae9cc0007c"
+    ],
+    -- COUNT = 5
+    [ "61f1471ced56aa04c57e1b512307d4cb92497d9592d7e9e35356e99d585cab1b"
+    , "84714e960c403a4fac06b2828cc564d9"
+    , ""
+    , "7bf97db3c102edc81596d4757045fe6bdc008f35792fc6290b77d889c09c33a8"
+    , "5b8bdc41f76d98cfa71ed976ea3994706375c8841adb8b6b3b6418e3132e8832"
+    , "94c8a8fdf38a6ccb8571c89420d899adab169214bb0dfcd43a04622e289935b2"
+    , "8a4b46e0a7a55907365f82d4ab9376509bd44728cab8cbafb0da901012ad8dcd"
+    , "933eb159a6af7455b60e40586c064f05f1970f564281b1ebc4662701ac1f299e4eb908c4afcb2e065191281ab576f684aefedd6904bad04d96bd93c0516c62a496c3073a0cda0676a11cc08866b0cc74f62cb9d3db48673b2c3fbeada69f922b4b795ccba22df12ef7125909381f7d681f6b9caba02fb913c5437b98c040c576"
+    ],
+    -- COUNT = 6
+    [ "a1d5bb7d70621dee6b668b28c56d5610c2f8ced30284cc3e0e48de331af05062"
+    , "88a49e3e54c5ea54c98b95de81bcc807"
+    , ""
+    , "b4e2426e98f6eed97a6cdf690a89ee109e84c3dca16c883c26fa4ac671638d8d"
+    , "5bd1e086ed228cfd8b55c1731fea40c3a63d022599ca2da4bb23118f4821ba62"
+    , "b754b53ac226e8ebe47a3d31496ec822de06fca2e7ef5bf1dec6c83d05368ec3"
+    , "fa7e76b2805d90b3d89fff545010d84f67aa3a2c9eb2ba232e75f4d53267dac3"
+    , "df6b2460688fa537df3ddfe5575fca5eb8abad56cbc4e5a618a2b4a7daf6e215c3a497974c502f9d0ec35de3fc2ea5d4f10de9b2aee66dcc7e7ae6357983095959b817f0383e3030771bd2ed97406acf78a1a4a5f30fa0992289c9202e69e3eb1eabe227c11409ff430f6dfca1a923a8b17bc4b87e908007f5e9759c41482b01"
+    ],
+    -- COUNT = 7
+    [ "68f21d14525d56233c7e263482d344c388a840103a77fb20ac60ce463cabdc79"
+    , "59fa80ae570f3e0c60ac7e2578cec3cb"
+    , ""
+    , "7584b4166530442f06e241dd904f562167e2fdae3247ab853a4a9d4884a5fa46"
+    , "f6a5482f139045c5389c9246d772c782c4ebf79c3a84b5cf779f458a69a52914"
+    , "9d37b1ce99f8079993ddf0bd54bab218016685b22655a678ce4300105f3a45b7"
+    , "4c97c67026ff43c2ee730e7b2ce8cce4794fd0588deb16185fa6792ddd0d46de"
+    , "e5f8874be0a8345aabf2f829a7c06bb40e60869508c2bdef071d73692c0265f6a5bf9ca6cf47d75cbd9df88b9cb236cdfce37d2fd4913f177dbd41887dae116edfbdad4fd6e4c1a51aad9f9d6afe7fcafced45a4913d742a7ec00fd6170d63a68f986d8c2357765e4d38835d3fea301afab43a50bd9edd2dec6a979732b25292"
+    ],
+    -- COUNT = 8
+    [ "7988146cbf9598d74cf88dc314af6b25c3f7de96ae9892fb0756318cea01987e"
+    , "280bc1ae9bfdf8a73c2df07b82a32c9c"
+    , ""
+    , "2bbc607085232e5e12ccf7c0c19a5dc80e45eb4b3d4a147fe941fa6c13333474"
+    , "f3f5c1bb5da59252861753c4980c23f72be1732f899fdea7183b5c024c858a12"
+    , "44d0cfc4f56ab38fa465a659151b3461b65b2462d1ad6b3463b5cf96ad9dc577"
+    , "34fb9a3cdacc834ff6241474c4f6e73ed6f5d9ea0337ab2b7468f01ad8a26e93"
+    , "4caec9e760c4d468e47613fe50de4a366ae20ba76793744a4e14433ea4de79dc188601eb86c803b094641ab2337b99d459d37decc7d27473057be45ba848868ee0fb5f1cf303d2fcd0b3e0c36f65a65f81b3fee8778a1f22302e25dfe34e6d587fa8864e621121880f7cd55f350531c4ce0530099eec2d0059706dcd657708d9"
+    ],
+    -- COUNT = 9
+    [ "1c974c953fa2a057c9fc9409a6843f6f839aa544bca4fa11e48afd77931d4656"
+    , "ed7c08285464af7a5dbdc10b944a1270"
+    , ""
+    , "78146ad135acb836360d36afc50653dcc36c21662da2a6f6ae05222e75f34000"
+    , "263c4984c238ded333c86472866353817379502157172cfa51371d82b1efd7b5"
+    , "79b591529f9a26a0d7c8f8fd64e354b0c134ef1f757e43f9463b3dbb7a3da1ab"
+    , "7d8f7204b0b5401ddce9e88dcf5facb9a44660a9f5f1c862748e7269c29f7964"
+    , "72e2ca257b9edaf59b50e05a144f56fb517832fb9ad3489b1e664e3d5412cbf6b2883e891703b2e73aff9ab56da1009fcdef010ab4cdab996795c8f7c47fb1192bb160353997ad39d7d5fd0e2efc9103a7c3f158246afd53fe53ca6782f809698ef5f1f0d85536780a3fd6a8bafa475891c09213088bd1a3dc169257c34a517a"
+    ],
+    -- COUNT = 10
+    [ "56216d71984a77154569122c777ce57e1d101a6025b28163a25971d39c1c5d0f"
+    , "5cd148ba7e54f4975ac8e3e0f9b5d06a"
+    , ""
+    , "3580f8ca974626c77259c6e37383cb8150b4d0ab0b30e377bed0dc9d1ff1a1bf"
+    , "15633e3a62b21594d49d3d26c4c3509f96011d4dbb9d48bbbea1b61c453f6abe"
+    , "6068eaca85c14165b101bb3e8c387c41d3f298918c7f3da2a28786ab0738a6fc"
+    , "e34f92d2b6aeeeea4ff49bfe7e4b1f462eabb853f0e86fbae0e8b3d51409ce49"
+    , "587fdb856abc19ede9078797ecb44099e07aadcd83acdcb2b090601d653f4a14c68ab2ebdda63578c5633a825bae4c0c818f89aac58d30fd7b0b5d459a0f3d86fcad78f4bb14dfff08ad81e4ea9f487cb426e91d6e80dfed436ba38fce8d6f21ca2151c92dd5c323b077d6139c66395558f0537026c4a028affa271ef4e7ea23"
+    ],
+    -- COUNT = 11
+    [ "83eb48bedc1e9294866ab8e5322ef83f6f271f8188e8fdabe5817788bd31570d"
+    , "d6ed90bc692237f132441ede857a6629"
+    , ""
+    , "a4e5e127f992bd5ca79ee56bb8a9bccf74c21814bfaf97ffd052211e802e12e4"
+    , "84136e403d9ed7f4515c188213abcfaca35715fa55de6d734aec63c4606a68f1"
+    , "fe9d8ef26e2d2e94b99943148392b2b33a581b4b97a8d7a0ecd41660a61dd10b"
+    , "594dad642183ce2cdc9494d6bcb358e0e7b767c5a0fa33e456971b8754a9abd5"
+    , "86715d43ba95fbbca9b7193ea977a820f4b61ba1b7e3b8d161b6c51b09dfd5040d94c04338b14d97ed25af577186b36ae7251a486c8a2d24a35e84a95c89d669d49e307b4a368b72164135ac54d020a970a180dfbed135d2c86f01270846d5301bd73db2c431a8aa10a0a3d03d146e5fafb9a2aa0b4efc80edab06ff3b532236"
+    ],
+    -- COUNT = 12
+    [ "ba2c94203dab2e6499d8c50dca7b5c34a6b4764834f9816631aa21b9f9c37361"
+    , "67db133bdefb25e395085bceee5a0afc"
+    , ""
+    , "fa8984d16d35302cda35a3a355ab9242ec96fec0652d39282d4a0abf0a80df87"
+    , "b6fed10255a3fea6772ae1ae6d9f6cbb9bfaa34804e58a5b786f9bc60b348ccd"
+    , "445e072244edc716d3528f0e0a20ff0cd8f819c0d031736c8da122748f24d6c6"
+    , "1f856e403c4fa035bac9aa81a20e347c7d8b213aab699d69d9d6186a06ac45c1"
+    , "79f33fc36b3b47d9ac805bdbbe699909a8d0beb689a8b2723c291bd5bf7f3ce61343d4722a14e4add36312dbb0594910c8828aff1abc159915d498106f9ffb31147478d8c9ef75d1536ba5036506b313f6e85033f8f6fea2a4de817c867a59378c53c70a2f108275daedd415c05b61c4fd5d48c54be9adb9dea6c40a2ec99ee0"
+    ],
+    -- COUNT = 13
+    [ "0db4c51492db4fe973b4bb1c52a1e873b58fc6bb37a3a4bfc252b03b994495d1"
+    , "a2a3900f169bba3f78a42526c700de62"
+    , ""
+    , "29d5aab356876447e3a20d81c7e3fc6975e2b984180a91493044442999e1ca3a"
+    , "40b34183b4e72cdff5952b317b3d45943d0fdcfa0527f3563055f7c73ae8f892"
+    , "dc94220c99ffb595c7c4d6de8de5a6bb4b38847169e24a557ef6d879ad84149d"
+    , "b2376626fd2f5218b3ed4a5609b43aa24d371cd2176ea017c2b99cf868060021"
+    , "f0bd6bc4c506d9427a09352d9c1970b146360732841a6323f4cb602c87dedfb5ff7e6964b9144933af3c5c83017ccd6a94bdca467a504564aaa7b452591a16ff6a1e7e94ddc98f9a58016cdcb8caaed6c80671ba48cc81a832d341093dda1d4e5001ec6bf66348b21e3692a13df92538ad572bb2023822072fc95f9590293ffc"
+    ],
+    --  COUNT = 14
+    [ "593845f0adfeffa7c169f8a610147ae8a08c0072fc0c14c3977d3de0d00b55af"
+    , "9e0eb2507342ee01c02beadee7d077bd"
+    , ""
+    , "aefe591697eab678c52e20013aa424b95cfd217b259757fbe17335563f5b5706"
+    , "cbb5be0ef9bf0555ee58955c4d971fb9baa6d6070c3f7244a4eb88b48f0793bf"
+    , "6dd878394abdc0402146ba07005327c55f4d821bfebca08d04e66824e3760ab4"
+    , "ba86a691d6cbf452b1e2fd1dfb5d31ef9ea5b8be92c4988dc5f560733b371f69"
+    , "00735cbfafac5df82e5cb28fc619b01e2ba9571dc0023d26f09c37fb37d0e809066165a97e532bf86fa7d148078e865fe1a09e27a6889be1533b459cd9cd229494b5cf4d2abf28c38180278d47281f13820276ec85effb8d45284eb9eef5d179ab4880023ab2bd08ee3f766f990286bf32430c042f5521bbfd0c7ee09e2254d7"
+    ]
+    ]
+
+{-
+    [SHA-256]
+    [PredictionResistance = False]
+    [EntropyInputLen = 256]
+    [NonceLen = 128]
+    [PersonalizationStringLen = 256]
+    [AdditionalInputLen = 0]
+    [ReturnedBitsLen = 1024]
+-}
+
+r3 :: [TestVector]
+r3 =
+    [
+    -- COUNT = 0
+    [ "fa0ee1fe39c7c390aa94159d0de97564342b591777f3e5f6a4ba2aea342ec840"
+    , "dd0820655cb2ffdb0da9e9310a67c9e5"
+    , "f2e58fe60a3afc59dad37595415ffd318ccf69d67780f6fa0797dc9aa43e144c"
+    , "e0629b6d7975ddfa96a399648740e60f1f9557dc58b3d7415f9ba9d4dbb501f6"
+    , ""
+    , ""
+    , ""
+    , "f92d4cf99a535b20222a52a68db04c5af6f5ffc7b66a473a37a256bd8d298f9b4aa4af7e8d181e02367903f93bdb744c6c2f3f3472626b40ce9bd6a70e7b8f93992a16a76fab6b5f162568e08ee6c3e804aefd952ddd3acb791c50f2ad69e9a04028a06a9c01d3a62aca2aaf6efe69ed97a016213a2dd642b4886764072d9cbe"
+    ],
+    -- COUNT = 1
+    [ "cff72f345115376a57f4db8a5c9f64053e7379171a5a1e81e82aad3448d17d44"
+    , "d1e971ec795d098b3dae14ffcbeecfd9"
+    , "6ec0c798c240f22740cad7e27b41f5e42dccaf66def3b7f341c4d827294f83c9"
+    , "45ec80f0c00cad0ff0b7616d2a930af3f5cf23cd61be7fbf7c65be0031e93e38"
+    , ""
+    , ""
+    , ""
+    , "17a7901e2550de088f472518d377cc4cc6979f4a64f4975c74344215e4807a1234eefef99f64cb8abc3fb86209f6fc7ddd03e94f83746c5abe5360cdde4f2525ccf7167e6f0befae05b38fd6089a2ab83719874ce8f670480d5f3ed9bf40538a15aaad112db1618a58b10687b68875f00f139a72bdf043f736e4a320c06efd2c"
+    ],
+    -- COUNT = 2
+    [ "b7099b06fc7a8a74c58219729db6b0f780d7b4fa307bc3d3f9f22bfb763596a3"
+    , "b8772059a135a6b61da72f375411de26"
+    , "2ac1bfb24e0b8c6ac2803e89261822b7f72a0320df2b199171b79bcbdb40b719"
+    , "9aec4f56ec5e96fbd96048b9a63ac8d047aedbbeea7712e241133b1a357ecfc4"
+    , ""
+    , ""
+    , ""
+    , "0e1f2bfef778f5e5be671ecb4971624ec784ed2732abc4fbb98a8b482fb68737df91fd15acfad2951403ac77c5ca3edffc1e03398ae6cf6ac24a91678db5c7290abc3fa001aa02d50399326f85d2b8942199a1575f6746364740a5910552c639804d7530c0d41339345a58ff0080eccf1711895192a3817a8dc3f00f28cc10cc"
+    ],
+    -- COUNT = 3
+    [ "7ba02a734c8744b15ef8b4074fe639b32e4431762ab5b7cd4d5df675ea90672b"
+    , "8a424f32108607c8f1f45d97f500ee12"
+    , "3ad627433f465187c48141e30c2678106091e7a680229a534b851b8d46feb957"
+    , "d8f02b59b6a3dd276bc69cba68efcf11ab83ead1397afd9841786bd1bb5da97a"
+    , ""
+    , ""
+    , ""
+    , "1fb91186ba4b4459d994b4b9f4ca252c7be6294d6cdb5fe56f8ff784d4b190a1c6456e0a41223bbbdf83ed8e7cfbfa765d9d8bc7ea5f4d79ea7eccb4928081a21de4cca36620d6267f55d9a352b76fc0a57375884112c31f65ff28e76d315698c29e6c4c05cb58b0a07ae66143b4abc78b9d25c78b4121e1e45bef1a6c1793e2"
+    ],
+    -- COUNT = 4
+    [ "9a8865dfe053ae77cb6a9365b88f34eec17ea5cbfb0b1f04d1459e7fa9c4f3cb"
+    , "180c0a74da3ec464df11fac172d1c632"
+    , "336372ec82d0d68befad83691966ef6ffc65105388eb2d6eed826c2285037c77"
+    , "75b95108eff1fabe83613e1c4de575e72a5cdc4bb9311dd006f971a052386692"
+    , ""
+    , ""
+    , ""
+    , "3c683f6d4f8f5a4018d01633dfee74266aaa68ed6fc649e81b64dfdf5f75e75d5c058d66cf5fd01a4f143a6ff695517a4a43bd3adfd1fb2c28ba9a41063140bedbffdb4d21b1ace1550d59209ec61f1e2dbacb2a9116a79cb1410bf2deca5218080aacd9c68e1d6557721a8913e23f617e30f2e594f61267d5ed81464ee730b2"
+    ],
+    -- COUNT = 5
+    [ "22c1af2f2a4c885f06988567da9fc90f34f80f6dd5101c281beef497a6a1b2f8"
+    , "3fafdecf79a4174801f133131629037b"
+    , "80327dac486111b8a8b2c8e8381fb2d713a67695c2e660b2b0d4af696cc3e1de"
+    , "f95a0e4bd24f0e2e9e444f511b7632868ead0d5bb3846771264e03f8ab8ed074"
+    , ""
+    , ""
+    , ""
+    , "77a7fea2f35a188f6d1bfdd49b569d8c45e2dd431d35a18c6f432c724f1e33ae92cb89a9cf91519e50705a53199f5b572dc85c1aef8f28fb52dc7986228f66954d54eda84a86962cf25cf765bd9949876349291b1aae5f88fcf4b376912d205add4f53b2770c657946c0d824281f441509153f48356d9d43f8a927e0693db8fc"
+    ],
+    -- COUNT = 6
+    [ "d0840e3a8d629d5b883d33e053a341b21c674e67e1999f068c497ecfaabfd6f6"
+    , "071de7244ecb2fdf7ab27f2d84aa7b7a"
+    , "90d609527fad96ffe64ab153860346f3d237c8940555ae17b47842d82d3b0943"
+    , "1dd1a8b59856c49a388f594c5f42cc2e4a56b3ccb8a65e7066e44c12f4344d50"
+    , ""
+    , ""
+    , ""
+    , "7ab28a9b2d3ae999195553e6550cced4c2daccbe7ec9dcbb0d467fabba185b727fbfd9830242cd098f4db3cf4a85e8bf8e8d5974b62b28550922b32ed5bfc1a522b6605cf93bf8d90bdec1c5b9e59c6fc37a817d437068a87254be1f7c4618ada46fbc3a2efb02e44524e21d91be7534cf05fbfd858304b706d6a91ea1cc6ad5"
+    ],
+    -- COUNT = 7
+    [ "2e2dd56869104492767a59778652831919e1c8b970f84e824ae4116597a0ab7f"
+    , "01c42a7e983641de46c82fd09b4f2f76"
+    , "bcd9e1508fcc22820a8be07180fea5045367333b569e111b011cd57dc1858765"
+    , "7306507cd3ca7eec667e640d270cfbb033063d97520b6b7e38ff3cea0e79d12b"
+    , ""
+    , ""
+    , ""
+    , "b915726c7b8c5dc3975f1a334684b973abf6a9495d930088cf5d071548e4fd29a67b55cc561ed6949ad28150a9fb4307c1fa5f783a7ea872e8d7c7e67ff0c2906081ee915737d813c25be5c30b952a36f393e6baa56ab01adc2b4776ad7b5d036a53659877c7a4e5220a897d6c0799af37beeed91173fbe9c613c3b6b9bb28e5"
+    ],
+    -- COUNT = 8
+    [ "d1aab0f16bd47a5ccd67c22e094daa3735eae21aa57f0bcd9e053d9d0d545cb8"
+    , "199310dfe1b01265b8c0d2b46d6c7c9f"
+    , "625b4b8f4de72ea9cb6f70556322dc2a19d6b2b32de623f557e419a084ba60fd"
+    , "f50cabae4e060f3971096b78e550cda2837a26a693d905db2d992d589b268f44"
+    , ""
+    , ""
+    , ""
+    , "987e1fdfe004c619cf1e9034576707eccd849400e19c87a1fef5b0179ec51c42a2f8c45d7942d0023a023c89f188b2634362703985695369863322f58619c50a7385a2dc91fc78f94b59f0131dc2b56a0d7c699d427285da1c104b0ad1739da10d8071c23993787045dc21f0070e1e9aa1658fc8e3add73dac7262e80e0aa2ee"
+    ],
+    -- COUNT = 9
+    [ "449480eaa100aff6f48dc6286a5a81b9728b084864f78a9da98f606a00a6a41f"
+    , "e53c6c5ac3da9f4726389a03f97bb640"
+    , "6b8fedc084d8e28d333aef6db3702b6351f0d24e30908cccb63794282655886b"
+    , "73a6d64e1966ae324388dc12c14544e9dc5ae4fcb331e99d350c456ff16f9aa0"
+    , ""
+    , ""
+    , ""
+    , "a06912d362da7eb25598857f6d65344c3e23ec3deb80c6e43158845b95eaeca241c0bbbd67ac385e24693444455cc1c2c08c1134d956b8bc93b28be9c2d3322b3e09252979dfb8d39d04c94f81bebda5c73110605a237b561216bda9ee9bdee1cc0c7728bcc8304682334ca944e467a27a85313fa5395a9c790e35defd2edb12"
+    ],
+    -- COUNT = 10
+    [ "9a6174166e97aa4981ddf580bc01c96754b9f0ba042750aabfda1cffe56e8581"
+    , "d7512ff6b7db7ce141b2bb01dcd0425e"
+    , "ed75288f23275f9422444da5d3b53ccb3c4ac8acfb659a1e9b7655c2db52f879"
+    , "6888b9277e57dc57663d402eba8d03cf56a070dc868e6a128b18040002baf690"
+    , ""
+    , ""
+    , ""
+    , "03519dfb2ff88cc2b53eecc48ae2a18ddcf91a5d69d5aefcdda8444e6df790a5240e67b2a4de75b4bb8a31f0f8aeb5e785ffb7a1341bb52fe00a05ee66fa2d44ea9956e055f9ffa6647c3bfe851ab364ade71a0d356de710ddafb7622b1da1bc53fd4d3210407289c68d8aeb346bf15806dbe787e781b94f63da3e1f61b5ac60"
+    ],
+    -- COUNT = 11
+    [ "9c6ae1002ee1b0add0be563ce50f899da936e13efa620d08c2688c192514763a"
+    , "fde7db5160c73044be73e9d4c1b22d86"
+    , "8fdaaeffd64e53f7b4374d902d441209964e12b65d29afec258e65db6de167ca"
+    , "bcc28fd58e397f53f494ad8132df82c5d8c4c22ea0b7139bd81eeba65667bb69"
+    , ""
+    , ""
+    , ""
+    , "021d938c9b4db780c7d8134aeff1053e5b8843370b8ae9a6749fca7199d809810f1bc8dfa49426470c30c3616f903e35fbacb23420a32f1bee567cc32300f704246ddc0217f236ef52c3ec9e2433ca66f05c25721f7661c43f22c1a125ed5db531bd0836eb435c27eefc7424ce9d845e1d4cc4c503097b4ffca788e674a5cb53"
+    ],
+    -- COUNT = 12
+    [ "fe96a85b69d46b540918927bb609dc57642eeaefd46bb5da2163a0bc60294b58"
+    , "22195a410d24db45589448dfe979d3fd"
+    , "20f698833a4472fd7b78fb9b0c4eb68604f166a2694c4af48dac2b2376790e1e"
+    , "09cb870879d3f734214f6a4bd2e08c62a2a954bebe559416d8c3551aafe71d6a"
+    , ""
+    , ""
+    , ""
+    , "d3e96dbe29e1fcb8ed83b19dbfb240e6f41679fbe83853aa71446617e63e5af78cf98b331d15bccb8c673c4e5d5dcec467a1fe26a6cd1696d0c9bc49f78139d051287df7f3ae0dbb4bbf581cb8211931063c3f4612ced53f59d1b4ebb875729139f5d2a7d60642e8f2835eed888b7e3e49c0dffd012cd746abfa3e1c5c2308c6"
+    ],
+    -- COUNT = 13
+    [ "a4fd693ff0a8af24bcec352d3196549fd0da5ee5d99ca58416ca03ce4c50f38e"
+    , "8cd67f2bf71d4366ce61396642531ff5"
+    , "368969c15a4849d7593be8b162113b9298a535c148ff668a9e8b147fb3af4eba"
+    , "83d2be9a0d74e6a42159ae630acebf4e15271ef7f14f3de14752be0e0e822b11"
+    , ""
+    , ""
+    , ""
+    , "e9188fc0eaec74b2608e21e3a40be94aaf4ae08eb684de8f8bba2d5fd3b073aa5531c938c0fc628da65725c54b5c68bb91d7d326565e96685e0a4e7b220c50e0caf1628edba5bd755b31894f8cb90afa76e88c5eb9e61b4932444c1397dee3e32241a3fb70a3929e49f6da02eea54812abb3d6b5cee18f03af1e0b4958430ab3"
+    ],
+    -- COUNT = 14
+    [ "254ff5687a6dad3f1d237dc762f58d24ef2e2c084d0a48d26a3dc81e5490cda3"
+    , "f2ec392acca491e03ce47b95963a49fc"
+    , "f806b9b4a56682c61b55cb6a334caf87ffe135adfea6d0c3fc22b39898fbd078"
+    , "b8494b1c1f1752fb6f80d732a89b08115857f7cc96e7dff05ebb822706889917"
+    , ""
+    , ""
+    , ""
+    , "0e527e00494d55564f9d9b28e7110f9a61ce36c883b5be2dcb055444164cdddd1a9f2731716f22d6ff476ce413c77abfc0e946871d5481345c2e97b4bfdd12ac03df606fc56bdb99ac7b71a69b5b9160373bbec3e9dde477180af454e7acc6bc58dc0afb4281c0de4354c1bf599054e3800c6d60d892858865b5361f50bfca9b"
+    ]
+    ]
+
+{-
+    [SHA-256]
+    [PredictionResistance = False]
+    [EntropyInputLen = 256]
+    [NonceLen = 128]
+    [PersonalizationStringLen = 256]
+    [AdditionalInputLen = 256]
+    [ReturnedBitsLen = 1024]
+-}
+
+r4 :: [TestVector]
+r4 =
+    [
+    -- COUNT = 0
+    [ "cdb0d9117cc6dbc9ef9dcb06a97579841d72dc18b2d46a1cb61e314012bdf416"
+    , "d0c0d01d156016d0eb6b7e9c7c3c8da8"
+    , "6f0fb9eab3f9ea7ab0a719bfa879bf0aaed683307fda0c6d73ce018b6e34faaa"
+    , "8ec6f7d5a8e2e88f43986f70b86e050d07c84b931bcf18e601c5a3eee3064c82"
+    , "1ab4ca9014fa98a55938316de8ba5a68c629b0741bdd058c4d70c91cda5099b3"
+    , "16e2d0721b58d839a122852abd3bf2c942a31c84d82fca74211871880d7162ff"
+    , "53686f042a7b087d5d2eca0d2a96de131f275ed7151189f7ca52deaa78b79fb2"
+    , "dda04a2ca7b8147af1548f5d086591ca4fd951a345ce52b3cd49d47e84aa31a183e31fbc42a1ff1d95afec7143c8008c97bc2a9c091df0a763848391f68cb4a366ad89857ac725a53b303ddea767be8dc5f605b1b95f6d24c9f06be65a973a089320b3cc42569dcfd4b92b62a993785b0301b3fc452445656fce22664827b88f"
+    ],
+    -- COUNT = 1
+    [ "3e42348bf76c0559cce9a44704308c85d9c205b676af0ac6ba377a5da12d3244"
+    , "9af783973c632a490f03dbb4b4852b1e"
+    , "2e51c7a8ac70adc37fc7e40d59a8e5bf8dfd8f7b027c77e6ec648bd0c41a78de"
+    , "45718ac567fd2660b91c8f5f1f8f186c58c6284b6968eadc9810b7beeca148a1"
+    , "63a107246a2070739aa4bed6746439d8c2ce678a54fc887c5aba29c502da7ba9"
+    , "e4576291b1cde51c5044fdc5375624cebf63333c58c7457ca7490da037a9556e"
+    , "b5a3fbd57784b15fd875e0b0c5e59ec5f089829fac51620aa998fff003534d6f"
+    , "c624d26087ffb8f39836c067ba37217f1977c47172d5dcb7d40193a1cfe20158b774558cbee8eb6f9c62d629e1bcf70a1439e46c5709ba4c94a006ba94994796e10660d6cb1e150a243f7ba5d35c8572fd96f43c08490131797e86d3ed8467b692f92f668631b1d32862c3dc43bfba686fe72fdd947db2792463e920522eb4bc"
+    ],
+    -- COUNT = 2
+    [ "b63fdd83c674699ba473faab9c358434771c5fa0348ca0faf7ebd7cf5891826b"
+    , "5fd204e2598d9626edab4158a8cfd95f"
+    , "2a5dfad8494306d9d4648a805c4602216a746ae3493492693a50a86d1ba05c64"
+    , "adea5ba92f8010bb1a6a4b6fae2caa0b384165adf721253afd635d6021f764af"
+    , "07c69d8d2b8aa1454c5c48083dd41477fda6bfcf0385638379933a60ed2e0a77"
+    , "a14e902247a3d6493d3fbc8519518b71a660e5502cf7ecfc796cfaa5b4ee4baa"
+    , "60e690e4a1eba14aec5187112a383e9991347fab7bac7cb2a40a52579a0d2718"
+    , "792b47b6ed221623bb187d63e3f039c6983d94efd5771dc9b4c40bee65924513485a6332baeda6a96f9bb431f592d73462b61d9d914a72b56fa9d87597426fb246424ebcd7abd51b2eefec8f5b839c0b3c34015342ace296b5f2218fa194b50aea1c89663460292c92c45f112ddbf6b9406f6e7ccee9c47ed2d90a27be5dd73e"
+    ],
+    -- COUNT = 3
+    [ "dab85f98eaf0cfba013b97de4d9c264ca6fe120366cb83e8b3113c68b34e39d5"
+    , "d05108e1028ae67b4ea63bdc6d75eb88"
+    , "09fed3822f6f5e5b9e575d31dc215de1607b0dfc927412618c2d8f79166dbaba"
+    , "1794885a64470744198b7d0bc24472ffe8daf3c7eb219df6ddf180e484fe0aa5"
+    , "8d74d01b582f70b92f53b43468084e1586d9b36465d333d5faaf6911e62fe40e"
+    , "ef7f6b6eb479ab05b3f9ab6dd72eac8b1e86d887f1bcae363cae386d0275a06f"
+    , "7442b2a792a6a29559bb8a515d56916ee18200580aa02e1237dd358619382d8f"
+    , "49d2cbfa0897b7d961c293c1e572fb26f28e7b956e746f6eda90454c1370a29e25303ceadc7837514dc638553b487ef9487c977c10625409178ad6506d103c487a66655d08659d92a4d5994d1c8ddb28fe60f2e49577d6e80cae1478068c98268f45e6293c9326c7f726ec89601351c0a26fd3a6549f8a41c6f58692c86594c0"
+    ],
+    -- COUNT = 4
+    [ "0f0aa84ef12e10ae2b279e799c683441862457b9bc25581c2cd3d5b58a5b3246"
+    , "f74f4230c2427a52f01f39e825d250ac"
+    , "d02b2f53da48b923c2921e0f75bd7e6139d7030aead5aeebe46c20b9ca47a38a"
+    , "5222b26e79f7c3b7066d581185b1a1f6376796f3d67f59d025dd2a7b1886d258"
+    , "d11512457bf3b92d1b1c0923989911f58f74e136b1436f00bad440dd1d6f1209"
+    , "54d9ea7d40b7255ef3d0ab16ea9fdf29b9a281920962b5c72d97b0e371b9d816"
+    , "601cef261da8864f1e30196c827143e4c363d3fa865b808e9450b13e251d47fa"
+    , "e9847cefea3b88062ea63f92dc9e96767ce9202a6e049c98dc1dcbc6d707687bd0e98ed2cc215780c454936292e44a7c6856d664581220b8c8ca1d413a2b81120380bfd0da5ff2bf737b602727709523745c2ced8daef6f47d1e93ef9bc141a135674cba23045e1f99aa78f8cead12eeffff20de2008878b1f806a2652db565a"
+    ],
+    -- COUNT = 5
+    [ "6a868ce39a3adcd189bd704348ba732936628f083de8208640dbd42731447d4e"
+    , "efdde4e22b376e5e7385e79024350699"
+    , "f7285cd5647ff0e2c71a9b54b57f04392641a4bde4a4024fa11c859fecaad713"
+    , "0174f7f456ac06c1d789facc071701f8b60e9accebced73a634a6ad0e1a697d4"
+    , "5463bb2241d10c970b68c3abc356c0fe5ef87439fc6457c5ee94be0a3fb89834"
+    , "3ab62cdbc638c1b2b50533d28f31b1758c3b8435fe24bb6d4740005a73e54ce6"
+    , "2dbf4c9123e97177969139f5d06466c272f60d067fefadf326ccc47971115469"
+    , "8afce49dccc4ff64c65a83d8c0638bd8e3b7c13c52c3c59d110a8198753e96da512c7e03aeed30918706f3ad3b819e6571cfa87369c179fb9c9bbc88110baa490032a9d41f9931434e80c40ae0051400b7498810d769fb42dddbc7aa19bdf79603172efe9c0f5d1a65372b463a31178cbae581fa287f39c4fbf8434051b7419f"
+    ],
+    -- COUNT = 6
+    [ "bb6b339eae26072487084ec9e4b53f2f1d4267d205042e74c77fb9ca0591ba50"
+    , "c0e7bf6eb07feccbc494af4098e59d30"
+    , "34aeec7ed0cae83701b6477709c8654a1114212401dc91cbe7de39d71f0c06e1"
+    , "f47fc60afbeb807236f7974d837335bc0b22288ef09ddfcb684e16b4c36a050b"
+    , "e8071ccd84ac4527e5c6e85b0709ed867776f25ae0e04180dcb7105ecd3e3490"
+    , "fbac45b5952200ad7c4232500f2417a1c14723bdd1cc078821bc2fe138b86597"
+    , "c4292d7dbef3ba7c18bf46bcf26776add22ab8ee206d6c722665dec6576b1bc0"
+    , "228aa2a314fcbfe63089ce953ac457093deaa39dd9ce2a4ece56a6028a476a98129be516d6979eff5587c032cdf4739d7ac712970f600fa781a8e542e399661183e34e4b90c59ec5dc5cad86f91083529d41c77b8f36c5a8e28ba1a548223a02eaed8426f6fe9f349ebec11bc743e767482e3472ec2799c1f530ebdc6c03bc4b"
+    ],
+    -- COUNT = 7
+    [ "be658e56f80436039e2a9c0a62952dd7d70842244b5ab10f3b8a87d36104e629"
+    , "33c9627455dfde91865aee93e5071147"
+    , "d3a6eb29b180b791984deb056d72c0608a2c9044237aecf100ccb03700064c5e"
+    , "bef24dc9a5aa23003d3825f9b2b00e7dab571ea6ad86415dbd30c0bbdce7b972"
+    , "047c29e4d1584fa70cb66e2aa148a2aa29837c5eee64dcac60fdba356cdf90bb"
+    , "41c4792161b1b00d410cb79cd56bd311a714fb78dc3471c25bdd7479f2e9a952"
+    , "cd4936d7bc3ea0e7201bcbefbc908215a97680ca6ce8672360aea600b6564308"
+    , "2c25557f6db07db057f56ad5b6dc0427d1a0e825c48c19a526f9a65087c6d1ead7c78363a61616c84f1022653af65173a3f9ec3275f2b0a0d0bc750194673c0eaa6c623cd88abb0c8979baee4cd85bfce2e4a20bfebf2c3be61676563767dfe229e0b7be67ad6fcd116dd0b460708b1b0e5c3d60f3dd8138030404d197375d75"
+    ],
+    -- COUNT = 8
+    [ "ae537f31a28ca14500e759716bc207983bfeab60b25079fa30b77b8d41244cb9"
+    , "fca9e27d8ab84cf9b9ce491ec5d8cb67"
+    , "8c9cb2b19aa3abe83c8fe7da96e9c11648252653a29dcd5bf0ac334ac587f032"
+    , "1eb52777be480f05115ae6370f30159a94d50ffcc64454678ab1d1ac6f166fa7"
+    , "9cdf6f1a2bc07acd4b0f43b5f2b892a1153e2669f237d257923636094fb40b54"
+    , "692d512722de6ba720fd23c8994ac63179b5f7e611addf9cfacd60e06e144a6a"
+    , "bbeea7b2bea821f339f494947c0b4bae8056119db69a3cbef21914953729cdef"
+    , "c0c4fb7080c0fbe425c1b756fb3a090cb0d08c7027d1bb82ed3b07613e2a757f83a78d42f9d8653954b489f800a5e058ebc4f5a1747526541d8448cb72e2232db20569dc96342c36672c4be625b363b4587f44557e58cedb4597cb57d006fda27e027818ae89e15b4c6382b9e7a4453290ea43163b4f9cae38b1023de6a47f7b"
+    ],
+    -- COUNT = 9
+    [ "2f8994c949e08862db0204008f55d3561f3e0362df13b9d9a70fda39938f2d33"
+    , "1bf3e94ea858160b832fe85d301256f5"
+    , "b46671cf7fa142e7012ed261e1fe86714711c246c7d1c0330fa692141e86d5d1"
+    , "5ecdb1e8fe12260b9bfe12d6e6f161474fa2311e12e39b0beb0fcd92a6737b73"
+    , "3ce9a29f0207d079e6dc81fb830356e555f96a23ea71424972ea9308965786d3"
+    , "db950000c0776cc0e049929ce021020adc42d29cd9b5d8f7117fbe6bde3e594f"
+    , "fc18ee6dd3dac2306774f0ac36cd789e33462d72a8c75df9057123db33e5f7bc"
+    , "8546362cc8af9b78dd6e8eb2c37db96e70708852bfd9380abedc7f324575a167bea18f632f3e19d099cfbf310773f9719eec036d2e09f393a023add8ebdc4fb87af43b2fe6c7eaa4d39f8022ce247aa45fdc84d1b92cacce6eae8252a03ec2ec5330c01f56d113fd2ec3d0240af0afcf13ddde205bb5e7c2d912dcb4aee5dcf3"
+    ],
+    -- COUNT = 10
+    [ "0c85e31487de1d7ba4a7b998ac56dc42c6dc0eae7bf5c8aaf1e4e78875f5fb47"
+    , "de878f728f73f83dc2a2f550b96c8b97"
+    , "9aac37bce1a6a81dc7934e23747991e3cf48c55ffe5a57781c41768a35220a01"
+    , "2d5ca8af1a70cfdccd015ee3bf0665dd1941fc6a7317b9d0d06658f5744cfbd9"
+    , "db881e6d0dc3b62793d7da5fe5a18e33be9b93f4a63a00a878dfbecf0d383bd2"
+    , "f743ce1b72f3de4c901369eed581c626ed3081ca707e6634fdaff46721ce0878"
+    , "cd52da3ec8a839c537dacdea8506a3eeee879de388ff5e513322d6d1bb3ff694"
+    , "a5bdd57cb8fde6298e7c5e563afcca60dd472eca484bd8c3cc17f3307be09b601744dd3ab9e8a44107c5868824575f850c0f399b280cf198006f83ede8c0b537e9be227fa140b65995ad9dfa1f2303d560c3b7f59bedd93c1282ea263924469411c2653f87fd814c74cb91c148430481d64bad0fec3cbb3dd1f39aa55c36f81b"
+    ],
+    -- COUNT = 11
+    [ "93161b2dc08cb0fd50171141c865a841ca935cfdd2b5907d6ff8ab0348c4ceb0"
+    , "5cb9f6e5912b90c3349a50ab881b35a1"
+    , "0dceb4a36326c4df1685df43fddeecb5d0c76f00eb44826694f27e610290f6e1"
+    , "d8e9be44b5f293482548d4787762ebfb03c73c40e45385e8b98907cd66f493dd"
+    , "105a8f85d6959f3e043ef508cfea21d52123f03b7aea8034c4eec761eaba1fee"
+    , "bf781f7e489d9b4b5aa5ee6d1796468af672a8d25f311edf3c4b4dbf433d703f"
+    , "c81d6bcf1e5bf37e39dda1735c6f193df115b1a854a12e7cafe060afe4589335"
+    , "4306628124d0100fade7eaaf5edf227d50771f9e5f2e1e983800eef9a39fde0b0c280e63c8728d836b5b93ea794a32c1c04cfc54bd5300e3febb5fe2e1023eded8d7cd180279a598f76823e8d5a7dffcc93a09deec5d1f80838e938fba4de9f47e94b99382ae55f116df9c3b3ddf7e50516e203645852a415796f03a86418107"
+    ],
+    -- COUNT = 12
+    [ "1ae12a5e4e9a4a5bfa79da30a9e6c62ffc639572ef1254194d129a16eb53c716"
+    , "5399b3481fdf24d373222267790a0fec"
+    , "8280cfdcd7a575816e0199e115da0ea77cae9d30b49c891a6c225e9037ba67e2"
+    , "681554ff702658122e91ba017450cfdfc8e3f4911153f7bcc428403e9c7b9d68"
+    , "226732b7a457cf0ac0ef09fd4f81296573b49a68de5e7ac3070e148c95e8e323"
+    , "45942b5e9a1a128e85e12c34596374ddc85fd7502e5633c7390fc6e6f1e5ef56"
+    , "6fc59929b41e77072886aff45f737b449b105ed7eacbd74c7cbfedf533dbeaa1"
+    , "b7547332e1509663fcfea2128f7f3a3df484cd8df034b00199157d35d61e35f1a9d481c7d2e81305616d70fc371ee459b0b2267d627e928590edcac3231898b24ef378aa9c3d381619f665379be76c7c1bd535505c563db3725f034786e35bdd90429305fd71d7bf680e8cdd6d4c348d97078f5cf5e89dee2dc410fad4f2a30f"
+    ],
+    -- COUNT = 13
+    [ "29e20d724dfa459960df21c6ec76b1e6cabd23a9e9456d6c591d7e4529da0ef8"
+    , "95df1f837eba47a1687aa5c4ddcf8aaf"
+    , "3713b601e164b1a51dda1ca9242ff477514648e90d311a06e10ce5aa15da5d7f"
+    , "2a2a312626ca3e20034fc4f28033c7d573f66ef61ab2ea0c7bf0411a9d247264"
+    , "ec68be33ac8ff3dd127e051604898c0f9a501271859376653a0516336180993d"
+    , "9935499661d699a00c622a875441b4df5204958fe95892c8ce67f7dfb2be3e4a"
+    , "256a4ba9e8f439d5487fa5eb45efcf1bc1120491724db3abe328d951f2739fc9"
+    , "73114cb3624d687d4cd49a6e769dfc7a3f8901dc41f6ad1df4ce480536fa82e52ae958d0528640d92b8bb981b755058e32c4733682e5c4c0df41f3505a1643a0dd49cfdeaf7a18adffca88256c6d2cceb838af6c92a64bc21cb7a760a0391291bfe3575e014fc156323f8eb5e86518c669dad8d29ad5fd4ef6e296f4a0764c26"
+    ],
+    -- COUNT = 14
+    [ "1353f3543eb1134980e061fc4382394975dbc74f1f1ea5ecc02780a813ac5ee6"
+    , "cf584db2447afbe2c8fa0c15575ee391"
+    , "345b0cc016f2765a8c33fc24f1dcfa182cbe29d7eacbcdc9bcda988521458fc2"
+    , "ba60219332a67b95d90ec9de6b8453d4c8af991ae9277461ff3af1b92fc985d3"
+    , "6964b9b9842aec9c7ec2aad926d701f30eec76fe699265ae2a7765d716958069"
+    , "6a03c28a9365c558c33d3fdc7e5ebf0b4d32caac70df71403fd70ced09757528"
+    , "a58546c72a0b4d47c9bd6c19e7cf4ab73b2d7ba36c6c6dc08606f608795ebd29"
+    , "5b029ef68b6799868b04dc28dbea26bc2fa9fcc8c2b2795aafeed0127b7297fa19a4ef2ba60c42ff8259d5a759f92bd90fdfb27145e82d798bb3ab7fd60bfaefb7aefb116ca2a4fa8b01d96a03c47c8d987fdd33c460e560b138891278313bb619d0c3c6f9d7c5a37e88fce83e94943705c6ff68e00484e74ad4097b0c9e5f10"
+    ]
+    ]
diff --git a/test/Network/Haskoin/Crypto/SignatureSpec.hs b/test/Network/Haskoin/Crypto/SignatureSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/Crypto/SignatureSpec.hs
@@ -0,0 +1,164 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Crypto.SignatureSpec (spec) where
+
+import           Data.Bits                 (testBit)
+import           Data.ByteString           (ByteString)
+import qualified Data.ByteString           as BS (index, length)
+import           Data.Maybe
+import           Data.Serialize            as S
+import           Data.Text                 (Text)
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Keys
+import           Network.Haskoin.Test
+import           Network.Haskoin.Util
+import           Test.Hspec
+import           Test.HUnit                (Assertion, assertBool)
+import           Test.QuickCheck
+
+spec :: Spec
+spec = do
+    describe "signatures" $ do
+        it "verify signature" $
+            property $
+            forAll arbitrarySignature $ \(msg, key, sig) ->
+                verifyHashSig msg sig (derivePubKey key)
+        it "s component less than half order" $
+            property $ forAll arbitrarySignature $ isCanonicalHalfOrder . lst3
+        it "encoded signature is canonical" $
+            property $ forAll arbitrarySignature $ testIsCanonical . lst3
+        it "encode signature and decode strictly" $
+            property $
+            forAll arbitrarySignature $
+            (\s -> decodeStrictSig (exportSig s) == Just s) . lst3
+        it "encodes and decodes signature" $
+            property $
+            forAll arbitrarySignature $
+            (\s -> decodeStrictSig (exportSig s) == Just s) . lst3
+    describe "trezor rfc6979 test vectors" $ do
+        it "rfc6979 test vector 1" (testSigning $ head detVec)
+        it "rfc6979 test vector 2" (testSigning $ detVec !! 1)
+        it "rfc6979 test vector 3" (testSigning $ detVec !! 2)
+        it "rfc6979 test vector 4" (testSigning $ detVec !! 3)
+        it "rfc6979 test vector 5" (testSigning $ detVec !! 4)
+        it "rfc6979 test vector 6" (testSigning $ detVec !! 5)
+        it "rfc6979 test vector 7" (testSigning $ detVec !! 6)
+        it "rfc6979 test vector 8" (testSigning $ detVec !! 7)
+        it "rfc6979 test vector 9" (testSigning $ detVec !! 8)
+        it "rfc6979 test vector 10" (testSigning $ detVec !! 9)
+        it "rfc6979 test vector 11" (testSigning $ detVec !! 10)
+        it "rfc6979 test vector 12" (testSigning $ detVec !! 11)
+
+testSigning :: (SecKey, ByteString, Text) -> Assertion
+testSigning (prv, msg, str) = do
+    assertBool "RFC 6979 Vector" $ res == fromJust (decodeHex str)
+    assertBool "valid sig" $ verifyHashSig msg' g (derivePubKey prv)
+  where
+    g = signHash prv msg'
+    msg' = sha256 msg
+    compact = exportCompactSig g
+    res = encode compact
+
+
+{- ECDSA Canonical -}
+
+-- github.com/bitcoin/bitcoin/blob/master/src/script.cpp
+-- from function IsCanonicalSignature
+testIsCanonical :: Sig -> Bool
+testIsCanonical sig = not $
+    -- Non-canonical signature: too short
+    (len < 8) ||
+    -- Non-canonical signature: too long
+    (len > 72) ||
+    -- Non-canonical signature: wrong type
+    (BS.index s 0 /= 0x30) ||
+    -- Non-canonical signature: wrong length marker
+    (BS.index s 1 /= len - 2) ||
+    -- Non-canonical signature: S length misplaced
+    (5 + rlen >= len) ||
+    -- Non-canonical signature: R+S length mismatch
+    (rlen + slen + 6 /= len) ||
+    -- Non-canonical signature: R value type mismatch
+    (BS.index s 2 /= 0x02) ||
+    -- Non-canonical signature: R length is zero
+    (rlen == 0) ||
+    -- Non-canonical signature: R value negative
+    testBit (BS.index s 4) 7 ||
+    -- Non-canonical signature: R value excessively padded
+    (  rlen > 1
+    && BS.index s 4 == 0
+    && not (testBit (BS.index s 5) 7)
+    ) ||
+    -- Non-canonical signature: S value type mismatch
+    (BS.index s (fromIntegral rlen + 4) /= 0x02) ||
+    -- Non-canonical signature: S length is zero
+    (slen == 0) ||
+    -- Non-canonical signature: S value negative
+    testBit (BS.index s (fromIntegral rlen+6)) 7 ||
+    -- Non-canonical signature: S value excessively padded
+    (  slen > 1
+    && BS.index s (fromIntegral rlen + 6) == 0
+    && not (testBit (BS.index s (fromIntegral rlen + 7)) 7)
+    )
+  where
+    s = exportSig sig
+    len = fromIntegral $ BS.length s
+    rlen = BS.index s 3
+    slen = BS.index s (fromIntegral rlen + 5)
+
+
+{- Trezor RFC 6979 Test Vectors -}
+-- github.com/trezor/python-ecdsa/blob/master/ecdsa/test_pyecdsa.py
+
+detVec :: [(SecKey, ByteString, Text)]
+detVec =
+    [
+      ( "0000000000000000000000000000000000000000000000000000000000000001"
+      , "Satoshi Nakamoto"
+      , "934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d82442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5"
+      )
+    , ( "0000000000000000000000000000000000000000000000000000000000000001"
+      , "All those moments will be lost in time, like tears in rain. Time to die..."
+      , "8600dbd41e348fe5c9465ab92d23e3db8b98b873beecd930736488696438cb6b547fe64427496db33bf66019dacbf0039c04199abb0122918601db38a72cfc21"
+      )
+    , ( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140"
+      , "Satoshi Nakamoto"
+      , "fd567d121db66e382991534ada77a6bd3106f0a1098c231e47993447cd6af2d06b39cd0eb1bc8603e159ef5c20a5c8ad685a45b06ce9bebed3f153d10d93bed5"
+      )
+    , ( "f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181"
+      , "Alan Turing"
+      , "7063ae83e7f62bbb171798131b4a0564b956930092b33b07b395615d9ec7e15c58dfcc1e00a35e1572f366ffe34ba0fc47db1e7189759b9fb233c5b05ab388ea"
+      )
+    , ( "e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2"
+      , "There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!"
+      , "b552edd27580141f3b2a5463048cb7cd3e047b97c9f98076c32dbdf85a68718b279fa72dd19bfae05577e06c7c0c1900c371fcd5893f7e1d56a37d30174671f6"
+      )
+    , ( "0000000000000000000000000000000000000000000000000000000000000001"
+      , "Everything should be made as simple as possible, but not simpler."
+      , "33a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c96f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262"
+      )
+    , ( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140"
+      , "Equations are more important to me, because politics is for the present, but an equation is something for eternity."
+      , "54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
+      )
+    , ( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140"
+      , "Not only is the Universe stranger than we think, it is stranger than we can think."
+      , "ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd06fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283"
+      )
+    , ( "0000000000000000000000000000000000000000000000000000000000000001"
+      , "How wonderful that we have met with a paradox. Now we have some hope of making progress."
+      , "c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d375afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3"
+      )
+    , ( "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64"
+      , "Computer science is no more about computers than astronomy is about telescopes."
+      , "7186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d0de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6"
+      )
+    , ( "00000000000000000000000000007246174ab1e92e9149c6e446fe194d072637"
+      , "...if you aren't, at any given time, scandalized by code you wrote five or even three years ago, you're not learning anywhere near enough"
+      , "fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda4870e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37"
+      )
+    , ( "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3"
+      , "The question of whether computers can think is like the question of whether submarines can swim."
+      , "cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf906ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef"
+      )
+    ]
diff --git a/test/Network/Haskoin/CryptoSpec.hs b/test/Network/Haskoin/CryptoSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/CryptoSpec.hs
@@ -0,0 +1,167 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.CryptoSpec (spec) where
+
+import           Control.Monad             (forM_, replicateM_)
+import           Control.Monad.Trans       (liftIO)
+import           Data.ByteString           (ByteString)
+import qualified Data.ByteString.Char8     as C (pack)
+import           Data.Maybe                (fromMaybe, isJust, isNothing)
+import           Data.Serialize            (encode)
+import           Data.Text                 (Text)
+import           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Keys
+import           Network.Haskoin.Util
+import           Test.Hspec
+import           Test.HUnit                (Assertion, assertBool)
+
+-- Unit tests copied from bitcoind implementation
+-- https://github.com/bitcoin/bitcoin/blob/master/src/test/key_tests.cpp
+
+strSecret1 :: Text
+strSecret1  = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj"
+
+strSecret2 :: Text
+strSecret2  = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3"
+
+strSecret1C :: Text
+strSecret1C = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw"
+
+strSecret2C :: Text
+strSecret2C = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g"
+
+addr1 :: Text
+addr1  = "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ"
+
+addr2 :: Text
+addr2  = "1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ"
+
+addr1C :: Text
+addr1C = "1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs"
+
+addr2C :: Text
+addr2C = "1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs"
+
+strAddressBad :: Text
+strAddressBad = "1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF"
+
+sigMsg :: [ByteString]
+sigMsg =
+    [ mconcat ["Very secret message ", C.pack (show (i :: Int)), ": 11"]
+    | i <- [0..15]
+    ]
+
+sec1 :: SecKeyI
+sec1 =
+    fromMaybe (error "Could not decode WIF secret 1") (fromWif btc strSecret1)
+
+sec2 :: SecKeyI
+sec2 =
+    fromMaybe (error "Could not decode WIF secret 2") (fromWif btc strSecret2)
+
+sec1C :: SecKeyI
+sec1C =
+    fromMaybe
+        (error "Could not decode WIF compressed secret 1")
+        (fromWif btc strSecret1C)
+
+sec2C :: SecKeyI
+sec2C =
+    fromMaybe
+        (error "Could not decode WIF compressed secret 2")
+        (fromWif btc strSecret2C)
+
+pub1 :: PubKeyI
+pub1  = derivePubKeyI sec1
+
+pub2 :: PubKeyI
+pub2  = derivePubKeyI sec2
+
+pub1C :: PubKeyI
+pub1C = derivePubKeyI sec1C
+
+pub2C :: PubKeyI
+pub2C = derivePubKeyI sec2C
+
+spec :: Spec
+spec =
+    describe "bitcoind /src/test/key_tests.cpp" $ do
+        it "decode valid wif" checkPrivkey
+        it "decode invalid wif" checkInvalidKey
+        it "decode minikey format" checkMiniKey
+        it "check private key compression" checkPrvKeyCompressed
+        it "check public key compression" checkKeyCompressed
+        it "check matching address" checkMatchingAddress
+        it "check various signatures" sigCheck
+
+sigCheck :: Assertion
+sigCheck = forM_ sigMsg $ checkSignatures . doubleSHA256
+
+{- bitcoind /src/test/key_tests.cpp -}
+
+checkPrivkey :: Assertion
+checkPrivkey = do
+    assertBool "Key 1"  $ isJust $ fromWif btc strSecret1
+    assertBool "Key 2"  $ isJust $ fromWif btc strSecret2
+    assertBool "Key 1C" $ isJust $ fromWif btc strSecret1C
+    assertBool "Key 2C" $ isJust $ fromWif btc strSecret2C
+
+checkInvalidKey :: Assertion
+checkInvalidKey =
+    assertBool "Bad key" $ isNothing $ fromWif btc strAddressBad
+
+checkMiniKey :: Assertion
+checkMiniKey =
+    assertBool "Bad mini key" $
+    isJust res && fromMiniKey "S6c56bnXQiBjk9mqSYE7ykVQ7NzrRy" == res
+  where
+    res = do
+        bs <-
+            decodeHex
+                "4C7A9640C72DC2099F23715D0C8A0D8A35F8906E3CAB61DD3F78B67BF887C9AB"
+        wrapSecKey False <$> secKey bs
+
+checkPrvKeyCompressed :: Assertion
+checkPrvKeyCompressed = do
+    assertBool "Key 1"  $ not $ secKeyCompressed sec1
+    assertBool "Key 2"  $ not $ secKeyCompressed sec2
+    assertBool "Key 1C" $ secKeyCompressed sec1C
+    assertBool "Key 2C" $ secKeyCompressed sec2C
+
+checkKeyCompressed :: Assertion
+checkKeyCompressed = do
+    assertBool "Key 1"  $ not $ pubKeyCompressed pub1
+    assertBool "Key 2"  $ not $ pubKeyCompressed pub2
+    assertBool "Key 1C" $ pubKeyCompressed pub1C
+    assertBool "Key 2C" $ pubKeyCompressed pub2C
+
+checkMatchingAddress :: Assertion
+checkMatchingAddress = do
+    assertBool "Key 1"  $ Just addr1  == addrToString (pubKeyAddr btc pub1)
+    assertBool "Key 2"  $ Just addr2  == addrToString (pubKeyAddr btc pub2)
+    assertBool "Key 1C" $ Just addr1C == addrToString (pubKeyAddr btc pub1C)
+    assertBool "Key 2C" $ Just addr2C == addrToString (pubKeyAddr btc pub2C)
+
+checkSignatures :: Hash256 -> Assertion
+checkSignatures h = do
+    let sign1  = signHash (secKeyData sec1) h
+        sign2  = signHash (secKeyData sec2) h
+        sign1C = signHash (secKeyData sec1C) h
+        sign2C = signHash (secKeyData sec2C) h
+    assertBool "Key 1, Sign1"   $ verifyHashSig h sign1 (pubKeyPoint pub1)
+    assertBool "Key 1, Sign2"   $ not $ verifyHashSig h sign2 (pubKeyPoint pub1)
+    assertBool "Key 1, Sign1C"  $ verifyHashSig h sign1C (pubKeyPoint pub1)
+    assertBool "Key 1, Sign2C"  $ not $ verifyHashSig h sign2C (pubKeyPoint pub1)
+    assertBool "Key 2, Sign1"   $ not $ verifyHashSig h sign1 (pubKeyPoint pub2)
+    assertBool "Key 2, Sign2"   $ verifyHashSig h sign2 (pubKeyPoint pub2)
+    assertBool "Key 2, Sign1C"  $ not $ verifyHashSig h sign1C (pubKeyPoint pub2)
+    assertBool "Key 2, Sign2C"  $ verifyHashSig h sign2C (pubKeyPoint pub2)
+    assertBool "Key 1C, Sign1"  $ verifyHashSig h sign1 (pubKeyPoint pub1C)
+    assertBool "Key 1C, Sign2"  $ not $ verifyHashSig h sign2 (pubKeyPoint pub1C)
+    assertBool "Key 1C, Sign1C" $ verifyHashSig h sign1C (pubKeyPoint pub1C)
+    assertBool "Key 1C, Sign2C" $ not $ verifyHashSig h sign2C (pubKeyPoint pub1C)
+    assertBool "Key 2C, Sign1"  $ not $ verifyHashSig h sign1 (pubKeyPoint pub2C)
+    assertBool "Key 2C, Sign2"  $ verifyHashSig h sign2 (pubKeyPoint pub2C)
+    assertBool "Key 2C, Sign1C" $ not $ verifyHashSig h sign1C (pubKeyPoint pub2C)
+    assertBool "Key 2C, Sign2C" $ verifyHashSig h sign2C (pubKeyPoint pub2C)
diff --git a/test/Network/Haskoin/Keys/ExtendedSpec.hs b/test/Network/Haskoin/Keys/ExtendedSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/Keys/ExtendedSpec.hs
@@ -0,0 +1,523 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Keys.ExtendedSpec (spec) where
+
+import           Data.Aeson                 as A
+import           Data.Aeson.Types           as A
+import           Data.Bits                  ((.&.))
+import           Data.ByteString            (ByteString)
+import qualified Data.ByteString.Lazy.Char8 as B8
+import           Data.Either                (isLeft)
+import           Data.Map.Strict            (singleton)
+import           Data.Maybe                 (fromJust, isJust, isNothing)
+import           Data.Serialize             as S
+import           Data.String                (fromString)
+import           Data.String.Conversions    (cs)
+import           Data.Text                  (Text)
+import           Data.Word                  (Word32)
+import           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Keys
+import           Network.Haskoin.Test
+import           Network.Haskoin.Util
+import           Test.Hspec
+import           Test.HUnit                 (Assertion, assertBool, assertEqual)
+import           Test.QuickCheck            hiding ((.&.))
+
+spec :: Spec
+spec = do
+    describe "bip32 derivation vector 1" $ do
+        it "chain m" $ runXKeyVec (head xKeyVec)
+        it "chain m/0'" $ runXKeyVec (xKeyVec !! 1)
+        it "chain m/0'/1" $ runXKeyVec (xKeyVec !! 2)
+        it "chain m/0'/1/2'" $ runXKeyVec (xKeyVec !! 3)
+        it "chain m/0'/1/2'/2" $ runXKeyVec (xKeyVec !! 4)
+        it "chain m/0'/1/2'/2/1000000000" $ runXKeyVec (xKeyVec !! 5)
+    describe "bip32 subkey derivation vector 2" $ do
+        it "chain m" $ runXKeyVec (head xKeyVec2)
+        it "chain m/0" $ runXKeyVec (xKeyVec2 !! 1)
+        it "chain m/0/2147483647'" $ runXKeyVec (xKeyVec2 !! 2)
+        it "chain m/0/2147483647'/1" $ runXKeyVec (xKeyVec2 !! 3)
+        it "chain m/0/2147483647'/1/2147483646'" $ runXKeyVec (xKeyVec2 !! 4)
+        it "Chain m/0/2147483647'/1/2147483646'/2" $ runXKeyVec (xKeyVec2 !! 5)
+    describe "bip32 subkey derivation using string path" $ do
+        it "either derivations" testApplyPath
+        it "either derivations" testBadApplyPath
+        it "dublic derivations" testDerivePubPath
+        it "private derivations" testDerivePrvPath
+        it "path parsing" testParsePath
+        it "from json" testFromJsonPath
+        it "to json" testToJsonPath
+    describe "extended keys" $ do
+        let net = btc
+        it "computes pubkey of a subkey is subkey of the pubkey" $
+            property $
+            forAll (arbitraryXPrvKey net) pubKeyOfSubKeyIsSubKeyOfPubKey
+        it "exports and imports extended private key" $
+            property $
+            forAll (arbitraryXPrvKey net) $ \k ->
+                xPrvImport net (xPrvExport k) == Just k
+        it "exports and imports extended public key" $
+            property $
+            forAll (arbitraryXPubKey net) $ \(_, k) ->
+                xPubImport net (xPubExport k) == Just k
+        it "show and read derivation path" $
+            property $ forAll arbitraryDerivPath $ \p -> read (show p) == p
+        it "show and read hard derivation path" $
+            property $ forAll arbitraryHardPath $ \p -> read (show p) == p
+        it "show and read soft derivation path" $
+            property $ forAll arbitrarySoftPath $ \p -> read (show p) == p
+        it "from string derivation path" $
+            property $
+            forAll arbitraryDerivPath $ \p -> fromString (cs $ pathToStr p) == p
+        it "from string hard derivation path" $
+            property $
+            forAll arbitraryHardPath $ \p -> fromString (cs $ pathToStr p) == p
+        it "from string soft derivation path" $
+            property $
+            forAll arbitrarySoftPath $ \p -> fromString (cs $ pathToStr p) == p
+        it "from and to lists of derivation paths" $
+            property $
+            forAll arbitraryDerivPath $ \p -> listToPath (pathToList p) == p
+        it "from and to lists of hard derivation paths" $
+            property $
+            forAll arbitraryHardPath $ \p ->
+                toHard (listToPath $ pathToList p) == Just p
+        it "from and to lists of soft derivation paths" $
+            property $
+            forAll arbitrarySoftPath $ \p ->
+                toSoft (listToPath $ pathToList p) == Just p
+        it "read and show parsed path" $
+            property $ forAll arbitraryParsedPath $ \p -> read (show p) == p
+        it "encodes and decodes extended private key" $
+            forAll (arbitraryXPrvKey net) (testCustom (xPrvFromJSON net))
+        it "encodes and decodes extended public key" $
+            forAll (arbitraryXPubKey net) (testCustom (xPubFromJSON net) . snd)
+        it "encodes and decodes derivation path" $
+            forAll arbitraryDerivPath testID
+        it "encodes and decodes parsed derivation path" $
+            forAll arbitraryParsedPath testID
+        it "encodes and decodes extended private key" $
+            property $
+            forAll (arbitraryXPrvKey net) $
+            testPutGet (getXPrvKey net) putXPrvKey
+        it "shows and reads extended private key" $
+            property $
+            forAll (arbitraryXPrvKey net) $ \k -> do
+                let k' = read (show k)
+                k' {xPrvNet = xPrvNet k} `shouldBe` k
+        it "shows and reads extended private key" $
+            property $
+            forAll (arbitraryXPubKey net) $ \(_, k) -> do
+                let k' = read (show k)
+                k' {xPubNet = xPubNet k} `shouldBe` k
+
+testFromJsonPath :: Assertion
+testFromJsonPath =
+    sequence_ $ do
+        path <- jsonPathVectors
+        return $
+            assertEqual
+                path
+                (Just [fromString path :: DerivPath])
+                (A.decode $ B8.pack $ "[\"" ++ path ++ "\"]")
+
+testToJsonPath :: Assertion
+testToJsonPath =
+    sequence_ $ do
+        path <- jsonPathVectors
+        return $
+            assertEqual
+                path
+                (B8.pack $ "[\"" ++ path ++ "\"]")
+                (A.encode [fromString path :: ParsedPath])
+
+jsonPathVectors :: [String]
+jsonPathVectors =
+    [ "m"
+    , "m/0"
+    , "m/0'"
+    , "M/0'"
+    , "m/2147483647"
+    , "M/2147483647"
+    , "m/1/2/3/4/5/6/7/8"
+    , "M/1/2/3/4/5/6/7/8"
+    , "m/1'/2'/3/4"
+    , "M/1'/2'/3/4"
+    ]
+
+testParsePath :: Assertion
+testParsePath =
+    sequence_ $ do
+        (path, t) <- parsePathVectors
+        return $ assertBool path (t $ parsePath path)
+
+parsePathVectors :: [(String, Maybe ParsedPath -> Bool)]
+parsePathVectors =
+    [ ("m", isJust)
+    , ("m/0'", isJust)
+    , ("M/0'", isJust)
+    , ("m/2147483648", isNothing)
+    , ("m/2147483647", isJust)
+    , ("M/2147483648", isNothing)
+    , ("M/2147483647", isJust)
+    , ("M/-1", isNothing)
+    , ("M/-2147483648", isNothing)
+    , ("m/1/2/3/4/5/6/7/8", isJust)
+    , ("M/1/2/3/4/5/6/7/8", isJust)
+    , ("m/1'/2'/3/4", isJust)
+    , ("M/1'/2'/3/4", isJust)
+    , ("m/1/2'/3/4'", isJust)
+    , ("M/1/2'/3/4'", isJust)
+    , ("meh", isNothing)
+    , ("infinity", isNothing)
+    , ("NaN", isNothing)
+    ]
+
+testApplyPath :: Assertion
+testApplyPath =
+    sequence_ $ do
+        (key, path, final) <- applyPathVectors
+        return $
+            assertEqual path final $ applyPath (fromJust $ parsePath path) key
+
+testBadApplyPath :: Assertion
+testBadApplyPath =
+    sequence_ $ do
+        (key, path) <- badApplyPathVectors
+        return $
+            assertBool path $ isLeft $ applyPath (fromJust $ parsePath path) key
+
+testDerivePubPath :: Assertion
+testDerivePubPath =
+    sequence_ $ do
+        (key, path, final) <- derivePubPathVectors
+        return $
+            assertEqual path final $
+            derivePubPath (fromString path :: SoftPath) key
+
+testDerivePrvPath :: Assertion
+testDerivePrvPath =
+    sequence_ $ do
+        (key, path, final) <- derivePrvPathVectors
+        return $
+            assertEqual path final $
+            derivePath (fromString path :: DerivPath) key
+
+derivePubPathVectors :: [(XPubKey, String, XPubKey)]
+derivePubPathVectors =
+    [ ( xpub, "M", xpub )
+    , ( xpub, "M/8", pubSubKey xpub 8 )
+    , ( xpub, "M/8/30/1", foldl pubSubKey xpub [8,30,1] )
+    ]
+  where
+    xprv = fromJust $ xPrvImport btc
+        "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\
+        \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB"
+    xpub = deriveXPubKey xprv
+
+derivePrvPathVectors :: [(XPrvKey, String, XPrvKey)]
+derivePrvPathVectors =
+    [ ( xprv, "m", xprv )
+    , ( xprv, "M", xprv )
+    , ( xprv, "m/8'", hardSubKey xprv 8 )
+    , ( xprv, "M/8'", hardSubKey xprv 8 )
+    , ( xprv, "m/8'/30/1"
+      , foldl prvSubKey (hardSubKey xprv 8) [30,1]
+      )
+    , ( xprv, "M/8'/30/1"
+      , foldl prvSubKey (hardSubKey xprv 8) [30,1]
+      )
+    , ( xprv, "m/3/20"
+      , foldl prvSubKey xprv [3,20]
+      )
+    , ( xprv, "M/3/20"
+      , foldl prvSubKey xprv [3,20]
+      )
+    ]
+  where
+    xprv = fromJust $ xPrvImport btc
+        "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\
+        \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB"
+
+applyPathVectors :: [(XKey, String, Either String XKey)]
+applyPathVectors =
+    [ (XPrv xprv btc, "m", Right (XPrv xprv btc))
+    , (XPrv xprv btc, "M", Right (XPub xpub btc))
+    , (XPrv xprv btc, "m/8'", Right (XPrv (hardSubKey xprv 8) btc))
+    , ( XPrv xprv btc
+      , "M/8'"
+      , Right (XPub (deriveXPubKey (hardSubKey xprv 8)) btc))
+    , ( XPrv xprv btc
+      , "m/8'/30/1"
+      , Right (XPrv (foldl prvSubKey (hardSubKey xprv 8) [30, 1]) btc))
+    , ( XPrv xprv btc
+      , "M/8'/30/1"
+      , Right
+            (XPub
+                 (deriveXPubKey (foldl prvSubKey (hardSubKey xprv 8) [30, 1]))
+                 btc))
+    , (XPrv xprv btc, "m/3/20", Right (XPrv (foldl prvSubKey xprv [3, 20]) btc))
+    , ( XPrv xprv btc
+      , "M/3/20"
+      , Right (XPub (deriveXPubKey (foldl prvSubKey xprv [3, 20])) btc))
+    , ( XPub xpub btc
+      , "M/3/20"
+      , Right (XPub (deriveXPubKey (foldl prvSubKey xprv [3, 20])) btc))
+    ]
+  where
+    xprv =
+        fromJust $
+        xPrvImport
+            btc
+            "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\
+        \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB"
+    xpub = deriveXPubKey xprv
+
+badApplyPathVectors :: [(XKey, String)]
+badApplyPathVectors =
+    [ (XPub xpub btc, "m/8'")
+    , (XPub xpub btc, "M/8'")
+    , (XPub xpub btc, "M/1/2/3'/4/5")
+    ]
+  where
+    xprv =
+        fromJust $
+        xPrvImport
+            btc
+            "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\
+        \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB"
+    xpub = deriveXPubKey xprv
+
+
+runXKeyVec :: ([Text], XPrvKey) -> Assertion
+runXKeyVec (v, m) = do
+    assertBool "xPrvID" $ encodeHex (S.encode $ xPrvID m) == head v
+    assertBool "xPrvFP" $ encodeHex (S.encode $ xPrvFP m) == v !! 1
+    assertBool "xPrvAddr" $
+        addrToString (xPubAddr $ deriveXPubKey m) == Just (v !! 2)
+    assertBool "prvKey" $ encodeHex (getSecKey $ xPrvKey m) == v !! 3
+    assertBool "xPrvWIF" $ xPrvWif m == v !! 4
+    assertBool "pubKey" $
+        encodeHex (exportPubKey True $ xPubKey $ deriveXPubKey m) == v !! 5
+    assertBool "chain code" $ encodeHex (S.encode $ xPrvChain m) == v !! 6
+    assertBool "Hex PubKey" $
+        encodeHex (runPut $ putXPubKey $ deriveXPubKey m) == v !! 7
+    assertBool "Hex PrvKey" $ encodeHex (runPut (putXPrvKey m)) == v !! 8
+    assertBool "Base58 PubKey" $ xPubExport (deriveXPubKey m) == v !! 9
+    assertBool "Base58 PrvKey" $ xPrvExport m == v !! 10
+
+-- BIP 0032 Test Vectors
+-- https://en.bitcoin.it/wiki/BIP_0032_TestVectors
+
+xKeyVec :: [([Text], XPrvKey)]
+xKeyVec = zip xKeyResVec $ foldl f [m] der
+    where f acc d = acc ++ [d $ last acc]
+          m   = makeXPrvKey btc $ fromJust $ decodeHex m0
+          der = [ flip hardSubKey 0
+                , flip prvSubKey 1
+                , flip hardSubKey 2
+                , flip prvSubKey 2
+                , flip prvSubKey 1000000000
+                ]
+
+xKeyVec2 :: [([Text], XPrvKey)]
+xKeyVec2 = zip xKeyResVec2 $ foldl f [m] der
+    where f acc d = acc ++ [d $ last acc]
+          m   = makeXPrvKey btc $ fromJust $ decodeHex m1
+          der = [ flip prvSubKey 0
+                , flip hardSubKey 2147483647
+                , flip prvSubKey 1
+                , flip hardSubKey 2147483646
+                , flip prvSubKey 2
+                ]
+
+m0 :: Text
+m0 = "000102030405060708090a0b0c0d0e0f"
+
+xKeyResVec :: [[Text]]
+xKeyResVec =
+    [
+      -- m
+      [ "3442193e1bb70916e914552172cd4e2dbc9df811"
+      , "3442193e"
+      , "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma"
+      , "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"
+      , "L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW"
+      , "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"
+      , "873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508"
+      , "0488b21e000000000000000000873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d5080339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"
+      , "0488ade4000000000000000000873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d50800e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"
+      , "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
+      , "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
+      ]
+      -- m/0'
+    , [ "5c1bd648ed23aa5fd50ba52b2457c11e9e80a6a7"
+      , "5c1bd648"
+      , "19Q2WoS5hSS6T8GjhK8KZLMgmWaq4neXrh"
+      , "edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"
+      , "L5BmPijJjrKbiUfG4zbiFKNqkvuJ8usooJmzuD7Z8dkRoTThYnAT"
+      , "035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"
+      , "47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141"
+      , "0488b21e013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"
+      , "0488ade4013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae623614100edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"
+      , "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"
+      , "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"
+      ]
+      -- m/0'/1
+    , [ "bef5a2f9a56a94aab12459f72ad9cf8cf19c7bbe"
+      , "bef5a2f9"
+      , "1JQheacLPdM5ySCkrZkV66G2ApAXe1mqLj"
+      , "3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"
+      , "KyFAjQ5rgrKvhXvNMtFB5PCSKUYD1yyPEe3xr3T34TZSUHycXtMM"
+      , "03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"
+      , "2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19"
+      , "0488b21e025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c1903501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"
+      , "0488ade4025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19003c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"
+      , "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"
+      , "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"
+      ]
+      -- m/0'/1/2'
+    , [ "ee7ab90cde56a8c0e2bb086ac49748b8db9dce72"
+      , "ee7ab90c"
+      , "1NjxqbA9aZWnh17q1UW3rB4EPu79wDXj7x"
+      , "cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"
+      , "L43t3od1Gh7Lj55Bzjj1xDAgJDcL7YFo2nEcNaMGiyRZS1CidBVU"
+      , "0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"
+      , "04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f"
+      , "0488b21e03bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"
+      , "0488ade403bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f00cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"
+      , "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"
+      , "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM"
+      ]
+      -- m/0'/1/2'/2
+    , [ "d880d7d893848509a62d8fb74e32148dac68412f"
+      , "d880d7d8"
+      , "1LjmJcdPnDHhNTUgrWyhLGnRDKxQjoxAgt"
+      , "0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"
+      , "KwjQsVuMjbCP2Zmr3VaFaStav7NvevwjvvkqrWd5Qmh1XVnCteBR"
+      , "02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"
+      , "cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd"
+      , "0488b21e04ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"
+      , "0488ade404ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd000f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"
+      , "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"
+      , "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334"
+      ]
+      -- m/0'/1/2'/2/1000000000
+    , [ "d69aa102255fed74378278c7812701ea641fdf32"
+      , "d69aa102"
+      , "1LZiqrop2HGR4qrH1ULZPyBpU6AUP49Uam"
+      , "471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"
+      , "Kybw8izYevo5xMh1TK7aUr7jHFCxXS1zv8p3oqFz3o2zFbhRXHYs"
+      , "022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"
+      , "c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e"
+      , "0488b21e05d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"
+      , "0488ade405d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e00471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"
+      , "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"
+      , "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"
+      ]
+    ]
+
+m1 :: Text
+m1 = "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"
+
+xKeyResVec2 :: [[Text]]
+xKeyResVec2 =
+    [
+      -- m
+      [ "bd16bee53961a47d6ad888e29545434a89bdfe95"
+      , "bd16bee5"
+      , "1JEoxevbLLG8cVqeoGKQiAwoWbNYSUyYjg"
+      , "4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"
+      , "KyjXhyHF9wTphBkfpxjL8hkDXDUSbE3tKANT94kXSyh6vn6nKaoy"
+      , "03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"
+      , "60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689"
+      , "0488b21e00000000000000000060499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd968903cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"
+      , "0488ade400000000000000000060499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689004b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"
+      , "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"
+      , "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"
+      ]
+      -- m/0
+    , [ "5a61ff8eb7aaca3010db97ebda76121610b78096"
+      , "5a61ff8e"
+      , "19EuDJdgfRkwCmRzbzVBHZWQG9QNWhftbZ"
+      , "abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"
+      , "L2ysLrR6KMSAtx7uPqmYpoTeiRzydXBattRXjXz5GDFPrdfPzKbj"
+      , "02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"
+      , "f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"
+      , "0488b21e01bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"
+      , "0488ade401bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c00abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"
+      , "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"
+      , "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt"
+      ]
+      -- m/0/2147483647'
+    , [ "d8ab493736da02f11ed682f88339e720fb0379d1"
+      , "d8ab4937"
+      , "1Lke9bXGhn5VPrBuXgN12uGUphrttUErmk"
+      , "877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"
+      , "L1m5VpbXmMp57P3knskwhoMTLdhAAaXiHvnGLMribbfwzVRpz2Sr"
+      , "03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"
+      , "be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9"
+      , "0488b21e025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d903c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"
+      , "0488ade4025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d900877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"
+      , "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"
+      , "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9"
+      ]
+      -- m/0/2147483647'/1
+    , [ "78412e3a2296a40de124307b6485bd19833e2e34"
+      , "78412e3a"
+      , "1BxrAr2pHpeBheusmd6fHDP2tSLAUa3qsW"
+      , "704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"
+      , "KzyzXnznxSv249b4KuNkBwowaN3akiNeEHy5FWoPCJpStZbEKXN2"
+      , "03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"
+      , "f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb"
+      , "0488b21e03d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"
+      , "0488ade403d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb00704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"
+      , "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"
+      , "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef"
+      ]
+      -- m/0/2147483647'/1/2147483646'
+    , [ "31a507b815593dfc51ffc7245ae7e5aee304246e"
+      , "31a507b8"
+      , "15XVotxCAV7sRx1PSCkQNsGw3W9jT9A94R"
+      , "f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"
+      , "L5KhaMvPYRW1ZoFmRjUtxxPypQ94m6BcDrPhqArhggdaTbbAFJEF"
+      , "02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"
+      , "637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29"
+      , "0488b21e0478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e2902d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"
+      , "0488ade40478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e2900f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"
+      , "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"
+      , "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc"
+      ]
+      -- m/0/2147483647'/1/2147483646'/2
+    , [ "26132fdbe7bf89cbc64cf8dafa3f9f88b8666220"
+      , "26132fdb"
+      , "14UKfRV9ZPUp6ZC9PLhqbRtxdihW9em3xt"
+      , "bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"
+      , "L3WAYNAZPxx1fr7KCz7GN9nD5qMBnNiqEJNJMU1z9MMaannAt4aK"
+      , "024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"
+      , "9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271"
+      , "0488b21e0531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"
+      , "0488ade40531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed27100bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"
+      , "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"
+      , "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"
+      ]
+    ]
+
+pubKeyOfSubKeyIsSubKeyOfPubKey :: XPrvKey -> Word32 -> Bool
+pubKeyOfSubKeyIsSubKeyOfPubKey k i =
+    deriveXPubKey (prvSubKey k i') == pubSubKey (deriveXPubKey k) i'
+  where
+    i' = fromIntegral $ i .&. 0x7fffffff -- make it a public derivation
+
+
+testID :: (FromJSON a, ToJSON a, Eq a) => a -> Bool
+testID x =
+    (A.decode . A.encode) (singleton ("object" :: String) x) ==
+    Just (singleton ("object" :: String) x)
+
+testCustom :: (ToJSON a, Eq a) => (Value -> Parser a) -> a -> Bool
+testCustom f x = parseMaybe f (toJSON x) == Just x
+
+testPutGet :: Eq a => Get a -> Putter a -> a -> Bool
+testPutGet g p a = runGet g (runPut (p a)) == Right a
diff --git a/test/Network/Haskoin/Keys/MnemonicSpec.hs b/test/Network/Haskoin/Keys/MnemonicSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/Keys/MnemonicSpec.hs
@@ -0,0 +1,494 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.Keys.MnemonicSpec (spec) where
+
+import           Control.Monad           (zipWithM_)
+import           Data.Bits               (shiftR, (.&.))
+import           Data.ByteString         (ByteString)
+import qualified Data.ByteString         as BS
+import qualified Data.ByteString.Char8   as C
+import           Data.Either             (fromRight)
+import           Data.List               (isPrefixOf)
+import           Data.Maybe              (fromJust)
+import           Data.Serialize          (Serialize, encode)
+import           Data.String.Conversions (cs)
+import           Data.Text               (Text)
+import qualified Data.Text               as T
+import           Data.Word               (Word32, Word64)
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Keys
+import           Network.Haskoin.Test
+import           Network.Haskoin.Util
+import           Test.Hspec
+import           Test.HUnit
+import           Test.QuickCheck         hiding ((.&.))
+
+spec :: Spec
+spec =
+    describe "mnemonic" $ do
+        it "entropy to mnemonic sentence" toMnemonicTest
+        it "mnemonic sentence to entropy" fromMnemonicTest
+        it "mnemonic sentence to seed" mnemonicToSeedTest
+        it "mnemonic sentence with invalid checksum" fromMnemonicInvalidTest
+        it "empty mnemonic sentence is invalid" $ sequence_ [emptyMnemonicTest]
+        it "generate 12 words" $ property toMnemonic128
+        it "generate 18 words" $ property toMnemonic160
+        it "generate 24 words" $ property toMnemonic256
+        it "generate 48 words" $ property toMnemonic512
+        it "generate any number of words" $ property toMnemonicVar
+        it "encode and decode 128-bit entropy" $ property fromToMnemonic128
+        it "encode and decode 160-bit entropy" $ property fromToMnemonic160
+        it "encode and decode 256-bit entropy" $ property fromToMnemonic256
+        it "encode and decode 512-bit entropy" $ property fromToMnemonic512
+        it "encode and decode n-bit entropy" $ property fromToMnemonicVar
+        it "convert 128-bit mnemonic to seed" $ property mnemonicToSeed128
+        it "convert 160-bit mnemonic to seed" $ property mnemonicToSeed160
+        it "convert 256-bit mnemonic to seed" $ property mnemonicToSeed256
+        it "convert 512-bit mnemonic to seed" $ property mnemonicToSeed512
+        it "convert n-bit mnemonic to seed" $ property mnemonicToSeedVar
+        it "get bits" $ property getBitsByteCount
+        it "get end bits" $ property getBitsEndBits
+
+toMnemonicTest :: Assertion
+toMnemonicTest = zipWithM_ f ents mss
+  where
+    f e m = assertEqual "" m . h $ e
+    h =
+        fromRight (error "Could not decode mnemonic sentence") .
+        toMnemonic . fromJust . decodeHex
+
+fromMnemonicTest :: Assertion
+fromMnemonicTest = zipWithM_ f ents mss
+  where
+    f e = assertEqual "" e . h
+    h =
+        encodeHex .
+        fromRight (error "Could not decode mnemonic sentence") . fromMnemonic
+
+mnemonicToSeedTest :: Assertion
+mnemonicToSeedTest = zipWithM_ f mss seeds
+  where
+    f m s = assertEqual "" s . h $ m
+    h =
+        encodeHex .
+        fromRight (error "Could not decode mnemonic seed") .
+        mnemonicToSeed "TREZOR"
+
+fromMnemonicInvalidTest :: Assertion
+fromMnemonicInvalidTest = mapM_ f invalidMss
+  where
+    f = assertBool "" . h
+    h m = case fromMnemonic m of
+            Right _  -> False
+            Left err -> "fromMnemonic: checksum failed:" `isPrefixOf` err
+
+emptyMnemonicTest :: Assertion
+emptyMnemonicTest =
+    assertBool "" $
+    case fromMnemonic "" of
+        Right _  -> False
+        Left err -> "fromMnemonic: empty mnemonic" `isPrefixOf` err
+
+ents :: [Text]
+ents =
+    [ "00000000000000000000000000000000"
+    , "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f"
+    , "80808080808080808080808080808080"
+    , "ffffffffffffffffffffffffffffffff"
+    , "000000000000000000000000000000000000000000000000"
+    , "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f"
+    , "808080808080808080808080808080808080808080808080"
+    , "ffffffffffffffffffffffffffffffffffffffffffffffff"
+    , "0000000000000000000000000000000000000000000000000000000000000000"
+    , "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f"
+    , "8080808080808080808080808080808080808080808080808080808080808080"
+    , "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+    , "77c2b00716cec7213839159e404db50d"
+    , "b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b"
+    , "3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982"
+    , "0460ef47585604c5660618db2e6a7e7f"
+    , "72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f"
+    , "2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416"
+    , "eaebabb2383351fd31d703840b32e9e2"
+    , "7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78"
+    , "4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef"
+    , "18ab19a9f54a9274f03e5209a2ac8a91"
+    , "18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4"
+    , "15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419"
+    ]
+
+mss :: [Mnemonic]
+mss =
+    [ "abandon abandon abandon abandon abandon abandon abandon abandon abandon\
+      \ abandon abandon about"
+    , "legal winner thank year wave sausage worth useful legal winner thank\
+      \ yellow"
+    , "letter advice cage absurd amount doctor acoustic avoid letter advice\
+      \ cage above"
+    , "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong"
+    , "abandon abandon abandon abandon abandon abandon abandon abandon abandon\
+      \ abandon abandon abandon abandon abandon abandon abandon abandon agent"
+    , "legal winner thank year wave sausage worth useful legal winner thank\
+      \ year wave sausage worth useful legal will"
+    , "letter advice cage absurd amount doctor acoustic avoid letter advice\
+      \ cage absurd amount doctor acoustic avoid letter always"
+    , "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo\
+      \ when"
+    , "abandon abandon abandon abandon abandon abandon abandon abandon abandon\
+      \ abandon abandon abandon abandon abandon abandon abandon abandon abandon\
+      \ abandon abandon abandon abandon abandon art"
+    , "legal winner thank year wave sausage worth useful legal winner thank\
+      \ year wave sausage worth useful legal winner thank year wave sausage\
+      \ worth title"
+    , "letter advice cage absurd amount doctor acoustic avoid letter advice\
+      \ cage absurd amount doctor acoustic avoid letter advice cage absurd\
+      \ amount doctor acoustic bless"
+    , "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo\
+      \ zoo zoo zoo zoo zoo vote"
+    , "jelly better achieve collect unaware mountain thought cargo oxygen act\
+      \ hood bridge"
+    , "renew stay biology evidence goat welcome casual join adapt armor shuffle\
+      \ fault little machine walk stumble urge swap"
+    , "dignity pass list indicate nasty swamp pool script soccer toe leaf photo\
+      \ multiply desk host tomato cradle drill spread actor shine dismiss\
+      \ champion exotic"
+    , "afford alter spike radar gate glance object seek swamp infant panel\
+      \ yellow"
+    , "indicate race push merry suffer human cruise dwarf pole review arch keep\
+      \ canvas theme poem divorce alter left"
+    , "clutch control vehicle tonight unusual clog visa ice plunge glimpse\
+      \ recipe series open hour vintage deposit universe tip job dress radar\
+      \ refuse motion taste"
+    , "turtle front uncle idea crush write shrug there lottery flower risk\
+      \ shell"
+    , "kiss carry display unusual confirm curtain upgrade antique rotate hello\
+      \ void custom frequent obey nut hole price segment"
+    , "exile ask congress lamp submit jacket era scheme attend cousin alcohol\
+      \ catch course end lucky hurt sentence oven short ball bird grab wing top"
+    , "board flee heavy tunnel powder denial science ski answer betray cargo\
+      \ cat"
+    , "board blade invite damage undo sun mimic interest slam gaze truly\
+      \ inherit resist great inject rocket museum chief"
+    , "beyond stage sleep clip because twist token leaf atom beauty genius food\
+      \ business side grid unable middle armed observe pair crouch tonight away\
+      \ coconut"
+    ]
+
+seeds :: [Text]
+seeds =
+    [ "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a69\
+      \87599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04"
+    , "2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6fa457fe1\
+      \296106559a3c80937a1c1069be3a3a5bd381ee6260e8d9739fce1f607"
+    , "d71de856f81a8acc65e6fc851a38d4d7ec216fd0796d0a6827a3ad6ed5511a30fa280f1\
+      \2eb2e47ed2ac03b5c462a0358d18d69fe4f985ec81778c1b370b652a8"
+    , "ac27495480225222079d7be181583751e86f571027b0497b5b5d11218e0a8a133325729\
+      \17f0f8e5a589620c6f15b11c61dee327651a14c34e18231052e48c069"
+    , "035895f2f481b1b0f01fcf8c289c794660b289981a78f8106447707fdd9666ca06da5a9\
+      \a565181599b79f53b844d8a71dd9f439c52a3d7b3e8a79c906ac845fa"
+    , "f2b94508732bcbacbcc020faefecfc89feafa6649a5491b8c952cede496c214a0c7b3c3\
+      \92d168748f2d4a612bada0753b52a1c7ac53c1e93abd5c6320b9e95dd"
+    , "107d7c02a5aa6f38c58083ff74f04c607c2d2c0ecc55501dadd72d025b751bc27fe913f\
+      \fb796f841c49b1d33b610cf0e91d3aa239027f5e99fe4ce9e5088cd65"
+    , "0cd6e5d827bb62eb8fc1e262254223817fd068a74b5b449cc2f667c3f1f985a76379b43\
+      \348d952e2265b4cd129090758b3e3c2c49103b5051aac2eaeb890a528"
+    , "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4\
+      \d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8"
+    , "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146a\
+      \d717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87"
+    , "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61a\
+      \f0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f"
+    , "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0\
+      \a5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad"
+    , "b5b6d0127db1a9d2226af0c3346031d77af31e918dba64287a1b44b8ebf63cdd52676f6\
+      \72a290aae502472cf2d602c051f3e6f18055e84e4c43897fc4e51a6ff"
+    , "9248d83e06f4cd98debf5b6f010542760df925ce46cf38a1bdb4e4de7d21f5c39366941\
+      \c69e1bdbf2966e0f6e6dbece898a0e2f0a4c2b3e640953dfe8b7bbdc5"
+    , "ff7f3184df8696d8bef94b6c03114dbee0ef89ff938712301d27ed8336ca89ef9635da2\
+      \0af07d4175f2bf5f3de130f39c9d9e8dd0472489c19b1a020a940da67"
+    , "65f93a9f36b6c85cbe634ffc1f99f2b82cbb10b31edc7f087b4f6cb9e976e9faf76ff41\
+      \f8f27c99afdf38f7a303ba1136ee48a4c1e7fcd3dba7aa876113a36e4"
+    , "3bbf9daa0dfad8229786ace5ddb4e00fa98a044ae4c4975ffd5e094dba9e0bb289349db\
+      \e2091761f30f382d4e35c4a670ee8ab50758d2c55881be69e327117ba"
+    , "fe908f96f46668b2d5b37d82f558c77ed0d69dd0e7e043a5b0511c48c2f1064694a956f\
+      \86360c93dd04052a8899497ce9e985ebe0c8c52b955e6ae86d4ff4449"
+    , "bdfb76a0759f301b0b899a1e3985227e53b3f51e67e3f2a65363caedf3e32fde42a66c4\
+      \04f18d7b05818c95ef3ca1e5146646856c461c073169467511680876c"
+    , "ed56ff6c833c07982eb7119a8f48fd363c4a9b1601cd2de736b01045c5eb8ab4f57b079\
+      \403485d1c4924f0790dc10a971763337cb9f9c62226f64fff26397c79"
+    , "095ee6f817b4c2cb30a5a797360a81a40ab0f9a4e25ecd672a3f58a0b5ba0687c096a6b\
+      \14d2c0deb3bdefce4f61d01ae07417d502429352e27695163f7447a8c"
+    , "6eff1bb21562918509c73cb990260db07c0ce34ff0e3cc4a8cb3276129fbcb300bddfe0\
+      \05831350efd633909f476c45c88253276d9fd0df6ef48609e8bb7dca8"
+    , "f84521c777a13b61564234bf8f8b62b3afce27fc4062b51bb5e62bdfecb23864ee6ecf0\
+      \7c1d5a97c0834307c5c852d8ceb88e7c97923c0a3b496bedd4e5f88a9"
+    , "b15509eaa2d09d3efd3e006ef42151b30367dc6e3aa5e44caba3fe4d3e352e65101fbdb\
+      \86a96776b91946ff06f8eac594dc6ee1d3e82a42dfe1b40fef6bcc3fd"
+    ]
+
+invalidMss :: [Mnemonic]
+invalidMss =
+    [ "abandon abandon abandon abandon abandon abandon abandon abandon abandon\
+      \ abandon abandon abandon"
+    , "legal winner thank year wave sausage worth useful legal winner thank\
+      \ thank"
+    , "letter advice cage absurd amount doctor acoustic avoid letter advice\
+      \ cage sausage"
+    , "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo"
+    , "abandon abandon abandon abandon abandon abandon abandon abandon abandon\
+      \ abandon abandon abandon abandon abandon abandon abandon abandon abandon"
+    , "legal winner thank year wave sausage worth useful legal winner thank\
+      \ year wave sausage worth useful legal letter"
+    , "letter advice cage absurd amount doctor acoustic avoid letter advice\
+      \ cage absurd amount doctor acoustic avoid letter abandon"
+    , "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo\
+      \ zoo"
+    , "abandon abandon abandon abandon abandon abandon abandon abandon abandon\
+      \ abandon abandon abandon abandon abandon abandon abandon abandon abandon\
+      \ abandon abandon abandon abandon abandon abandon"
+    , "legal winner thank year wave sausage worth useful legal winner thank\
+      \ year wave sausage worth useful legal winner thank year wave sausage\
+      \ worth letter"
+    , "letter advice cage absurd amount doctor acoustic avoid letter advice\
+      \ cage absurd amount doctor acoustic avoid letter advice cage absurd\
+      \ amount doctor acoustic letter"
+    , "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo\
+      \ zoo zoo zoo zoo zoo zoo"
+    , "jelly better achieve collect unaware mountain thought cargo oxygen act\
+      \ hood zoo"
+    , "renew stay biology evidence goat welcome casual join adapt armor shuffle\
+      \ fault little machine walk stumble urge zoo"
+    , "dignity pass list indicate nasty swamp pool script soccer toe leaf photo\
+      \ multiply desk host tomato cradle drill spread actor shine dismiss\
+      \ champion zoo"
+    , "afford alter spike radar gate glance object seek swamp infant panel\
+      \ zoo"
+    , "indicate race push merry suffer human cruise dwarf pole review arch keep\
+      \ canvas theme poem divorce alter zoo"
+    , "clutch control vehicle tonight unusual clog visa ice plunge glimpse\
+      \ recipe series open hour vintage deposit universe tip job dress radar\
+      \ refuse motion zoo"
+    , "turtle front uncle idea crush write shrug there lottery flower risk\
+      \ zoo"
+    , "kiss carry display unusual confirm curtain upgrade antique rotate hello\
+      \ void custom frequent obey nut hole price zoo"
+    , "exile ask congress lamp submit jacket era scheme attend cousin alcohol\
+      \ catch course end lucky hurt sentence oven short ball bird grab wing zoo"
+    , "board flee heavy tunnel powder denial science ski answer betray cargo\
+      \ zoo"
+    , "board blade invite damage undo sun mimic interest slam gaze truly\
+      \ inherit resist great inject rocket museum zoo"
+    , "beyond stage sleep clip because twist token leaf atom beauty genius food\
+      \ business side grid unable middle armed observe pair crouch tonight away\
+      \ zoo"
+    ]
+
+binWordsToBS :: Serialize a => [a] -> BS.ByteString
+binWordsToBS = foldr f BS.empty
+  where
+    f b a = a `BS.append` encode b
+
+{- Encode mnemonic -}
+
+toMnemonic128 :: (Word64, Word64) -> Bool
+toMnemonic128 (a, b) = l == 12
+  where
+    bs = encode a `BS.append` encode b
+    l =
+        length .
+        T.words . fromRight (error "Could not decode mnemonic senttence") $
+        toMnemonic bs
+
+toMnemonic160 :: (Word32, Word64, Word64) -> Bool
+toMnemonic160 (a, b, c) = l == 15
+  where
+    bs = BS.concat [encode a, encode b, encode c]
+    l =
+        length .
+        T.words . fromRight (error "Colud not decode mnemonic sentence") $
+        toMnemonic bs
+
+toMnemonic256 :: (Word64, Word64, Word64, Word64) -> Bool
+toMnemonic256 (a, b, c, d) = l == 24
+  where
+    bs = BS.concat [encode a, encode b, encode c, encode d]
+    l =
+        length .
+        T.words . fromRight (error "Could not decode mnemonic sentence") $
+        toMnemonic bs
+
+toMnemonic512 ::
+    ((Word64, Word64, Word64, Word64), (Word64, Word64, Word64, Word64)) -> Bool
+toMnemonic512 ((a, b, c, d), (e, f, g, h)) = l == 48
+  where
+    bs =
+        BS.concat
+            [ encode a
+            , encode b
+            , encode c
+            , encode d
+            , encode e
+            , encode f
+            , encode g
+            , encode h
+            ]
+    l =
+        length .
+        T.words . fromRight (error "Colud not decode mnemoonic sentence") $
+        toMnemonic bs
+
+toMnemonicVar :: [Word32] -> Property
+toMnemonicVar ls = not (null ls) && length ls <= 8 ==> l == wc
+  where
+    bs = binWordsToBS ls
+    bl = BS.length bs
+    cb = bl `div` 4
+    wc = (cb + bl * 8) `div` 11
+    l =
+        length . T.words .
+        fromRight (error "Could not decode mnemonic sentence") $
+        toMnemonic bs
+
+{- Encode/Decode -}
+
+fromToMnemonic128 :: (Word64, Word64) -> Bool
+fromToMnemonic128 (a, b) = bs == bs'
+  where
+    bs = encode a `BS.append` encode b
+    bs' =
+        fromRight
+            (error "Colud not decode mnemonic entropy")
+            (fromMnemonic =<< toMnemonic bs)
+
+fromToMnemonic160 :: (Word32, Word64, Word64) -> Bool
+fromToMnemonic160 (a, b, c) = bs == bs'
+  where
+    bs = BS.concat [encode a, encode b, encode c]
+    bs' =
+        fromRight
+            (error "Could not decode mnemonic entropy")
+            (fromMnemonic =<< toMnemonic bs)
+
+fromToMnemonic256 :: (Word64, Word64, Word64, Word64) -> Bool
+fromToMnemonic256 (a, b, c, d) = bs == bs'
+  where
+    bs = BS.concat [encode a, encode b, encode c, encode d]
+    bs' =
+        fromRight
+            (error "Could not decode mnemonic entropy")
+            (fromMnemonic =<< toMnemonic bs)
+
+fromToMnemonic512 ::
+    ((Word64, Word64, Word64, Word64), (Word64, Word64, Word64, Word64)) -> Bool
+fromToMnemonic512 ((a, b, c, d), (e, f, g, h)) = bs == bs'
+  where
+    bs =
+        BS.concat
+            [ encode a
+            , encode b
+            , encode c
+            , encode d
+            , encode e
+            , encode f
+            , encode g
+            , encode h
+            ]
+    bs' =
+        fromRight
+            (error "Could not decode mnemonic entropy")
+            (fromMnemonic =<< toMnemonic bs)
+
+fromToMnemonicVar :: [Word32] -> Property
+fromToMnemonicVar ls = not (null ls) && length ls <= 8 ==> bs == bs'
+  where
+    bs = binWordsToBS ls
+    bs' =
+        fromRight
+            (error "Colud not decode mnemonic entropy")
+            (fromMnemonic =<< toMnemonic bs)
+
+{- Mnemonic to seed -}
+
+mnemonicToSeed128 :: (Word64, Word64) -> Bool
+mnemonicToSeed128 (a, b) = l == 64
+  where
+    bs = encode a `BS.append` encode b
+    seed =
+        fromRight
+            (error "Could not decode mnemonic seed")
+            (mnemonicToSeed "" =<< toMnemonic bs)
+    l = BS.length seed
+
+mnemonicToSeed160 :: (Word32, Word64, Word64) -> Bool
+mnemonicToSeed160 (a, b, c) = l == 64
+  where
+    bs = BS.concat [encode a, encode b, encode c]
+    seed =
+        fromRight
+            (error "Could not decode mnemonic seed")
+            (mnemonicToSeed "" =<< toMnemonic bs)
+    l = BS.length seed
+
+mnemonicToSeed256 :: (Word64, Word64, Word64, Word64) -> Bool
+mnemonicToSeed256 (a, b, c, d) = l == 64
+  where
+    bs = BS.concat [encode a, encode b, encode c, encode d]
+    seed =
+        fromRight
+            (error "Colud not decode mnemonic seed")
+            (mnemonicToSeed "" =<< toMnemonic bs)
+    l = BS.length seed
+
+mnemonicToSeed512 ::
+    ((Word64, Word64, Word64, Word64), (Word64, Word64, Word64, Word64)) -> Bool
+mnemonicToSeed512 ((a, b, c, d), (e, f, g, h)) = l == 64
+  where
+    bs =
+        BS.concat
+            [ encode a
+            , encode b
+            , encode c
+            , encode d
+            , encode e
+            , encode f
+            , encode g
+            , encode h
+            ]
+    seed =
+        fromRight
+            (error "Could not decode mnemonic seed")
+            (mnemonicToSeed "" =<< toMnemonic bs)
+    l = BS.length seed
+
+mnemonicToSeedVar :: [Word32] -> Property
+mnemonicToSeedVar ls = not (null ls) && length ls <= 16 ==> l == 64
+  where
+    bs = binWordsToBS ls
+    seed =
+        fromRight
+            (error "Could not decode mnemonic seed")
+            (mnemonicToSeed "" =<< toMnemonic bs)
+    l = BS.length seed
+
+{- Get bits from ByteString -}
+
+data ByteCountGen = ByteCountGen BS.ByteString Int deriving Show
+
+instance Arbitrary ByteCountGen where
+    arbitrary = do
+        bs <- arbitraryBS
+        i <- choose (0, BS.length bs * 8)
+        return $ ByteCountGen bs i
+
+getBitsByteCount :: ByteCountGen -> Bool
+getBitsByteCount (ByteCountGen bs i) = BS.length bits == l
+  where
+    (q, r) = i `quotRem` 8
+    bits = getBits i bs
+    l = if r == 0 then q else q + 1
+
+getBitsEndBits :: ByteCountGen -> Bool
+getBitsEndBits (ByteCountGen bs i) =
+    (r == 0) || (BS.last bits .&. (0xff `shiftR` r) == 0x00)
+  where
+    r = i `mod` 8
+    bits = getBits i bs
diff --git a/test/Network/Haskoin/KeysSpec.hs b/test/Network/Haskoin/KeysSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/KeysSpec.hs
@@ -0,0 +1,72 @@
+module Network.Haskoin.KeysSpec (spec) where
+
+import           Data.Aeson                as A
+import qualified Data.ByteString           as BS
+import           Data.Map.Strict           (singleton)
+import           Data.Serialize            as S
+import           Data.String               (fromString)
+import           Data.String.Conversions   (cs)
+import           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Keys
+import           Network.Haskoin.Test
+import           Network.Haskoin.Util
+import           Test.Hspec
+import           Test.QuickCheck
+
+spec :: Spec
+spec =
+    describe "keys" $ do
+        let net = btc
+        it "is public key canonical" $
+            property $ forAll arbitraryKeyPair (isCanonicalPubKey . snd)
+        it "encode and decode wif private keys" $
+            property $
+            forAll arbitraryKeyPair $ \(pk, _) ->
+                fromWif net (toWif net pk) == Just pk
+        it "encode and decode serialized private key" $
+            property $ forAll arbitrary binaryPrvKey
+        it "read and show public key" $
+            property $ forAll arbitraryKeyPair $ \(_, k) -> read (show k) == k
+        it "read and show private key" $
+            property $ forAll arbitrarySecKeyI $ \k -> read (show k) == k
+        it "from string public key" $
+            property $
+            forAll arbitraryKeyPair $ \(_, k) ->
+                fromString (cs . encodeHex $ S.encode k) == k
+        it "encode and decode json public key" $
+            property $ forAll arbitraryKeyPair (testID . snd)
+        it "encodes and decodes serialized public key" $
+            property $ forAll arbitraryKeyPair $ cerealID . snd
+
+
+-- github.com/bitcoin/bitcoin/blob/master/src/script.cpp
+-- from function IsCanonicalPubKey
+isCanonicalPubKey :: PubKeyI -> Bool
+isCanonicalPubKey p = not $
+    -- Non-canonical public key: too short
+    (BS.length bs < 33) ||
+    -- Non-canonical public key: invalid length for uncompressed key
+    (BS.index bs 0 == 4 && BS.length bs /= 65) ||
+    -- Non-canonical public key: invalid length for compressed key
+    (BS.index bs 0 `elem` [2,3] && BS.length bs /= 33) ||
+    -- Non-canonical public key: compressed nor uncompressed
+    (BS.index bs 0 `notElem` [2,3,4])
+  where
+    bs = S.encode p
+
+{- Key formats -}
+
+binaryPrvKey :: SecKey -> Bool
+binaryPrvKey k =
+    Right k == runGet secKeyGet (runPut (secKeyPut k)) &&
+    Just k == secKey (getSecKey k)
+
+testID :: (FromJSON a, ToJSON a, Eq a) => a -> Bool
+testID x =
+    (A.decode . A.encode) (singleton ("object" :: String) x) ==
+    Just (singleton ("object" :: String) x)
+
+cerealID :: (Serialize a, Eq a) => a -> Bool
+cerealID x = S.decode (S.encode x) == Right x
diff --git a/test/Network/Haskoin/NetworkSpec.hs b/test/Network/Haskoin/NetworkSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/NetworkSpec.hs
@@ -0,0 +1,112 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.NetworkSpec (spec) where
+
+import           Data.Aeson                as A
+import           Data.ByteString           (ByteString)
+import           Data.Maybe                (fromJust)
+import           Data.Serialize            as S
+import           Data.Text                 (Text)
+import           Data.Word                 (Word32)
+import           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Keys
+import           Network.Haskoin.Network
+import           Network.Haskoin.Test
+import           Network.Haskoin.Util
+import           Test.Hspec
+import           Test.HUnit                (Assertion, assertBool)
+import           Test.QuickCheck
+
+spec :: Spec
+spec = do
+    let net = btc
+    describe "bloom filters" $ do
+        it "bloom filter vector 1" bloomFilter1
+        it "bloom filter vector 2" bloomFilter2
+        it "bloom filter vector 3" bloomFilter3
+    describe "serialization of protocol types" $ do
+        it "encodes and decodes varint" $
+            property $ forAll arbitraryVarInt cerealID
+        it "encodes and decodes varstring" $
+            property $ forAll arbitraryVarString cerealID
+        it "encodes and decodes network address" $
+            property $ forAll arbitraryNetworkAddress cerealID
+        it "encodes and decodes invtype" $
+            property $ forAll arbitraryInvType cerealID
+        it "encodes and decodes invvector" $
+            property $ forAll arbitraryInvVector cerealID
+        it "encodes and decodes inv" $ property $ forAll arbitraryInv1 cerealID
+        it "encodes and decodes version" $
+            property $ forAll arbitraryVersion cerealID
+        it "encodes and decodes addr" $ property $ forAll arbitraryAddr1 cerealID
+        it "encodes and decodes alert" $ property $ forAll arbitraryAlert cerealID
+        it "encodes and decodes reject" $
+            property $forAll arbitraryReject cerealID
+        it "encodes and decodes getdata" $
+            property $ forAll arbitraryGetData cerealID
+        it "encodes and decodes notfound" $
+            property $ forAll arbitraryNotFound cerealID
+        it "encodes and decodes ping" $ property $ forAll arbitraryPing cerealID
+        it "encodes and decodes pong" $ property $ forAll arbitraryPong cerealID
+        it "encodes and decodes message command" $
+            property $ forAll arbitraryMessageCommand cerealID
+        it "encodes and decodes message header" $
+            property $ forAll arbitraryMessageHeader cerealID
+        it "encodes and decodes message" $
+            property $
+            forAll (arbitraryMessage net) $
+            testPutGet (getMessage net) (putMessage net)
+    describe "serialization of bloom types" $ do
+        it "encodes and decodes bloom flags" $
+            property $ forAll arbitraryBloomFlags cerealID
+        it "encodes and decodes bloom filter" $
+            property $ forAll arbitraryBloomFilter $ cerealID . lst3
+        it "encodes and decodes filterload" $
+            property $ forAll arbitraryFilterLoad cerealID
+        it "encodes and decodes filteradd" $
+            property $ forAll arbitraryFilterAdd cerealID
+
+bloomFilter :: Word32 -> Text -> Assertion
+bloomFilter n x = do
+    assertBool "Bloom filter doesn't contain vector 1" $ bloomContains f1 v1
+    assertBool "Bloom filter contains something it should not" $
+        not $ bloomContains f1 v2
+    assertBool "Bloom filter doesn't contain vector 3" $ bloomContains f3 v3
+    assertBool "Bloom filter doesn't contain vector 4" $ bloomContains f4 v4
+    assertBool "Bloom filter serialization is incorrect" $
+        S.encode f4 == bs
+  where
+    f0 = bloomCreate 3 0.01 n BloomUpdateAll
+    f1 = bloomInsert f0 v1
+    f3 = bloomInsert f1 v3
+    f4 = bloomInsert f3 v4
+    v1 = fromJust $ decodeHex "99108ad8ed9bb6274d3980bab5a85c048f0950c8"
+    v2 = fromJust $ decodeHex "19108ad8ed9bb6274d3980bab5a85c048f0950c8"
+    v3 = fromJust $ decodeHex "b5a2c786d9ef4658287ced5914b37a1b4aa32eee"
+    v4 = fromJust $ decodeHex "b9300670b4c5366e95b2699e8b18bc75e5f729c5"
+    bs = fromJust $ decodeHex x
+
+bloomFilter1 :: Assertion
+bloomFilter1 = bloomFilter 0 "03614e9b050000000000000001"
+
+bloomFilter2 :: Assertion
+bloomFilter2 = bloomFilter 2147483649 "03ce4299050000000100008001"
+
+bloomFilter3 :: Assertion
+bloomFilter3 =
+    assertBool "Bloom filter serialization is incorrect" $
+        S.encode f2 == bs
+  where
+    f0 = bloomCreate 2 0.001 0 BloomUpdateAll
+    f1 = bloomInsert f0 $ S.encode p
+    f2 = bloomInsert f1 $ S.encode $ getAddrHash160 $ pubKeyAddr btc p
+    k = fromJust $ fromWif btc "5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C"
+    p = derivePubKeyI k
+    bs = fromJust $ decodeHex "038fc16b080000000000000001"
+
+cerealID :: (Serialize a, Eq a) => a -> Bool
+cerealID x = S.decode (S.encode x) == Right x
+
+testPutGet :: Eq a => Get a -> Putter a -> a -> Bool
+testPutGet g p a = runGet g (runPut (p a)) == Right a
diff --git a/test/Network/Haskoin/ScriptSpec.hs b/test/Network/Haskoin/ScriptSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/ScriptSpec.hs
@@ -0,0 +1,473 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.ScriptSpec (spec) where
+
+import           Control.Monad
+import           Control.Monad.IO.Class
+import           Data.Aeson                  as A
+import           Data.ByteString             (ByteString)
+import qualified Data.ByteString             as BS
+import qualified Data.ByteString.Char8       as C
+import qualified Data.ByteString.Lazy        as BL
+import qualified Data.ByteString.Lazy.Char8  as CL
+import           Data.Char                   (ord)
+import           Data.Either
+import           Data.Int                    (Int64)
+import           Data.List
+import           Data.List.Split             (splitOn)
+import           Data.Map.Strict             (singleton)
+import           Data.Maybe
+import           Data.Monoid                 ((<>))
+import           Data.Serialize              as S
+import           Data.String
+import           Data.String.Conversions     (cs)
+import           Data.Text                   (Text)
+import           Data.Word
+import           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Keys
+import           Network.Haskoin.Script
+import           Network.Haskoin.Test
+import           Network.Haskoin.Transaction
+import           Network.Haskoin.Util
+import           Numeric                     (readHex)
+import           Test.Hspec
+import           Test.HUnit                  as HUnit
+import           Test.QuickCheck
+import           Text.Read
+
+spec :: Spec
+spec = do
+    let net = btc
+    describe "btc scripts" $ props btc
+    describe "bch scripts" $ props bch
+    describe "multi signatures" $
+        zipWithM_ (curry mapMulSigVector) mulSigVectors [0 ..]
+    describe "signature decoding" $
+        zipWithM_ (curry (sigDecodeMap net)) scriptSigSignatures [0 ..]
+    describe "json serialization" $ do
+        it "encodes and decodes script output" $
+            forAll (arbitraryScriptOutput net) testID
+        it "encodes and decodes outpoint" $ forAll arbitraryOutPoint testID
+        it "encodes and decodes sighash" $ forAll arbitrarySigHash testID
+        it "encodes and decodes siginput" $
+            forAll (arbitrarySigInput net) (testID . fst)
+    describe "script serialization" $ do
+        it "encodes and decodes script op" $
+            property $ forAll arbitraryScriptOp cerealID
+        it "encodes and decodes script" $
+            property $ forAll arbitraryScript cerealID
+
+props :: Network -> Spec
+props net = do
+    standardSpec net
+    strictSigSpec net
+    scriptSpec net
+    txSigHashForkIdSpec net
+    forkIdScriptSpec net
+    sigHashSpec net
+    txSigHashSpec net
+
+cerealID :: (Serialize a, Eq a) => a -> Bool
+cerealID x = S.decode (S.encode x) == Right x
+
+standardSpec :: Network -> Spec
+standardSpec net = do
+    it "has intToScriptOp . scriptOpToInt identity" $
+        property $
+        forAll arbitraryIntScriptOp $ \i ->
+            intToScriptOp <$> scriptOpToInt i `shouldBe` Right i
+    it "has decodeOutput . encodeOutput identity" $
+        property $
+        forAll (arbitraryScriptOutput net) $ \so ->
+            decodeOutput (encodeOutput so) `shouldBe` Right so
+    it "has decodeInput . encodeOutput identity" $
+        property $
+        forAll (arbitraryScriptInput net) $ \si ->
+            decodeInput net (encodeInput si) `shouldBe` Right si
+    it "can sort multisig scripts" $
+        forAll arbitraryMSOutput $ \out ->
+            map S.encode (getOutputMulSigKeys (sortMulSig out)) `shouldSatisfy` \xs ->
+                xs == sort xs
+    it "can decode inputs with empty signatures" $ do
+        decodeInput net (Script [OP_0]) `shouldBe`
+            Right (RegularInput (SpendPK TxSignatureEmpty))
+        decodeInput net (Script [opPushData ""]) `shouldBe`
+            Right (RegularInput (SpendPK TxSignatureEmpty))
+        let pk =
+                derivePubKeyI $
+                wrapSecKey True $ fromJust $ secKey $ BS.replicate 32 1
+        decodeInput net (Script [OP_0, opPushData $ S.encode pk]) `shouldBe`
+            Right (RegularInput (SpendPKHash TxSignatureEmpty pk))
+        decodeInput net (Script [OP_0, OP_0]) `shouldBe`
+            Right (RegularInput (SpendMulSig [TxSignatureEmpty]))
+        decodeInput net (Script [OP_0, OP_0, OP_0, OP_0]) `shouldBe`
+            Right (RegularInput (SpendMulSig $ replicate 3 TxSignatureEmpty))
+
+scriptSpec :: Network -> Spec
+scriptSpec net =
+    when (getNetworkName net == "btc") $
+    it "can verify standard scripts from script_tests.json file" $ do
+        xs <- readTestFile "script_tests" :: IO [A.Value]
+        let vectorsA =
+                mapMaybe (A.decode . A.encode) xs :: [( String
+                                                      , String
+                                                      , String
+                                                      , String
+                                                      , String)]
+            vectorsB =
+                mapMaybe (A.decode . A.encode) xs :: [( [Word64]
+                                                      , String
+                                                      , String
+                                                      , String
+                                                      , String
+                                                      , String)]
+            vectors =
+                map (\(a, b, c, d, e) -> ([0], a, b, c, d, e)) vectorsA <>
+                vectorsB
+        length vectors `shouldBe` 86
+        forM_ vectors $ \([val], siStr, soStr, flags, res, desc)
+          -- We can disable specific tests by adding a DISABLED flag in the data
+         ->
+            unless ("DISABLED" `isInfixOf` flags) $ do
+                let strict =
+                        "DERSIG" `isInfixOf` flags ||
+                        "STRICTENC" `isInfixOf` flags ||
+                        "NULLDUMMY" `isInfixOf` flags
+                    scriptSig = parseScript siStr
+                    scriptPubKey = parseScript soStr
+                    decodedOutput =
+                        fromRight (error $ "Could not decode output: " <> soStr) $
+                        decodeOutputBS scriptPubKey
+                    ver =
+                        verifyStdInput
+                            net
+                            (spendTx scriptPubKey 0 scriptSig)
+                            0
+                            decodedOutput
+                            (val * 100000000)
+                case res of
+                    "OK" -> assertBool desc ver
+                    _    -> assertBool desc (not ver)
+
+forkIdScriptSpec :: Network -> Spec
+forkIdScriptSpec net =
+    when (isJust (getSigHashForkId net)) $
+    it "can verify scripts from forkid_script_tests.json file" $ do
+        xs <- readTestFile "forkid_script_tests" :: IO [A.Value]
+        let vectors =
+                mapMaybe (A.decode . A.encode) xs :: [( [Word64]
+                                                      , String
+                                                      , String
+                                                      , String
+                                                      , String
+                                                      , String)]
+        length vectors `shouldBe` 3
+        forM_ vectors $ \([valBTC], siStr, soStr, _, res, _) -> do
+            let val = valBTC * 100000000
+                scriptSig = parseScript siStr
+                scriptPubKey = parseScript soStr
+                decodedOutput =
+                    fromRight (error $ "Could not decode output: " <> soStr) $
+                    decodeOutputBS scriptPubKey
+                ver =
+                    verifyStdInput
+                        net
+                        (spendTx scriptPubKey val scriptSig)
+                        0
+                        decodedOutput
+                        val
+            case res of
+                "OK" -> ver `shouldBe` True
+                _    -> ver `shouldBe` False
+
+creditTx :: BS.ByteString -> Word64 -> Tx
+creditTx scriptPubKey val =
+    Tx 1 [txI] [txO] [] 0
+  where
+    txO = TxOut {outValue = val, scriptOutput = scriptPubKey}
+    txI =
+        TxIn
+        { prevOutput = nullOutPoint
+        , scriptInput = S.encode $ Script [OP_0, OP_0]
+        , txInSequence = maxBound
+        }
+
+spendTx :: BS.ByteString -> Word64 -> BS.ByteString -> Tx
+spendTx scriptPubKey val scriptSig =
+    Tx 1 [txI] [txO] [] 0
+  where
+    txO = TxOut {outValue = val, scriptOutput = BS.empty}
+    txI =
+        TxIn
+        { prevOutput = OutPoint (txHash $ creditTx scriptPubKey val) 0
+        , scriptInput = scriptSig
+        , txInSequence = maxBound
+        }
+
+parseScript :: String -> BS.ByteString
+parseScript str =
+    BS.concat $ fromMaybe err $ mapM f $ words str
+  where
+    f = decodeHex . cs . dropHex . replaceToken
+    dropHex ('0':'x':xs) = xs
+    dropHex xs           = xs
+    err = error $ "Could not decode script: " <> str
+
+replaceToken :: String -> String
+replaceToken str = case readMaybe $ "OP_" <> str of
+    Just opcode -> "0x" <> cs (encodeHex $ S.encode (opcode :: ScriptOp))
+    _           -> str
+
+strictSigSpec :: Network -> Spec
+strictSigSpec net =
+    when (getNetworkName net == "btc") $ do
+        it "can decode strict signatures" $ do
+            xs <- readTestFile "sig_strict"
+            let vectors = mapMaybe decodeHex xs
+            length vectors `shouldBe` 3
+            forM_ vectors $ \sig ->
+                decodeTxSig net sig `shouldSatisfy` isRight
+        it "can detect non-strict signatures" $ do
+            xs <- readTestFile "sig_nonstrict"
+            let vectors = mapMaybe decodeHex xs
+            length vectors `shouldBe` 17
+            forM_ vectors $ \sig ->
+                decodeTxSig net sig `shouldSatisfy` isLeft
+
+txSigHashSpec :: Network -> Spec
+txSigHashSpec net =
+    when (getNetworkName net == "btc") $
+    it "can produce valid sighashes from sighash.json test vectors" $ do
+        xs <- readTestFile "sighash" :: IO [A.Value]
+        let vectors =
+                mapMaybe (A.decode . A.encode) xs :: [( String
+                                                      , String
+                                                      , Int
+                                                      , Integer
+                                                      , String)]
+        length vectors `shouldBe` 500
+        forM_ vectors $ \(txStr, scpStr, i, shI, resStr) -> do
+            let tx = fromString txStr
+                s =
+                    fromMaybe (error $ "Could not decode script: " <> cs scpStr) $
+                    eitherToMaybe . S.decode =<< decodeHex (cs scpStr)
+                sh = fromIntegral shI
+                res =
+                    eitherToMaybe . S.decode . BS.reverse =<<
+                    decodeHex (cs resStr)
+            Just (txSigHash net tx s 0 i sh) `shouldBe` res
+
+txSigHashForkIdSpec :: Network -> Spec
+txSigHashForkIdSpec net =
+    when (getNetworkName net == "btc") $
+    it "can produce valid sighashes from forkid_sighash.json test vectors" $ do
+        xs <- readTestFile "forkid_sighash" :: IO [A.Value]
+        let vectors =
+                mapMaybe (A.decode . A.encode) xs :: [( String
+                                                      , String
+                                                      , Int
+                                                      , Word64
+                                                      , Integer
+                                                      , String)]
+        length vectors `shouldBe` 13
+        forM_ vectors $ \(txStr, scpStr, i, val, shI, resStr) -> do
+            let tx = fromString txStr
+                s =
+                    fromMaybe (error $ "Could not decode script: " <> cs scpStr) $
+                    eitherToMaybe . S.decode =<< decodeHex (cs scpStr)
+                sh = fromIntegral shI
+                res = eitherToMaybe . S.decode =<< decodeHex (cs resStr)
+            Just (txSigHashForkId net tx s val i sh) `shouldBe` res
+
+sigHashSpec :: Network -> Spec
+sigHashSpec net = do
+    it "can read . show" $
+        property $ forAll arbitrarySigHash $ \sh -> read (show sh) `shouldBe` sh
+    it "can correctly show" $ do
+        show (0x00 :: SigHash) `shouldBe` "SigHash " <> show 0x00
+        show (0x01 :: SigHash) `shouldBe` "SigHash " <> show 0x01
+        show (0xff :: SigHash) `shouldBe` "SigHash " <> show 0xff
+        show (0xabac3344 :: SigHash) `shouldBe` "SigHash " <> show 0xabac3344
+    it "can add a forkid" $ do
+        0x00 `sigHashAddForkId` 0x00 `shouldBe` 0x00
+        0xff `sigHashAddForkId` 0x00ffffff `shouldBe` 0xffffffff
+        0xffff `sigHashAddForkId` 0x00aaaaaa `shouldBe` 0xaaaaaaff
+        0xffff `sigHashAddForkId` 0xaaaaaaaa `shouldBe` 0xaaaaaaff
+        0xffff `sigHashAddForkId` 0x00004444 `shouldBe` 0x004444ff
+        0xff01 `sigHashAddForkId` 0x44440000 `shouldBe` 0x44000001
+        0xff03 `sigHashAddForkId` 0x00550000 `shouldBe` 0x55000003
+    it "can extract a forkid" $ do
+        sigHashGetForkId 0x00000000 `shouldBe` 0x00000000
+        sigHashGetForkId 0x80000000 `shouldBe` 0x00800000
+        sigHashGetForkId 0xffffffff `shouldBe` 0x00ffffff
+        sigHashGetForkId 0xabac3403 `shouldBe` 0x00abac34
+    it "can build some vectors" $ do
+        sigHashAll `shouldBe` 0x01
+        sigHashNone `shouldBe` 0x02
+        sigHashSingle `shouldBe` 0x03
+        setForkIdFlag sigHashAll `shouldBe` 0x41
+        setAnyoneCanPayFlag sigHashAll `shouldBe` 0x81
+        setAnyoneCanPayFlag (setForkIdFlag sigHashAll) `shouldBe` 0xc1
+    it "can test flags" $ do
+        hasForkIdFlag sigHashAll `shouldBe` False
+        hasForkIdFlag (setForkIdFlag sigHashAll) `shouldBe` True
+        hasAnyoneCanPayFlag sigHashAll `shouldBe` False
+        hasAnyoneCanPayFlag (setAnyoneCanPayFlag sigHashAll) `shouldBe` True
+        isSigHashAll sigHashNone `shouldBe` False
+        isSigHashAll sigHashAll `shouldBe` True
+        isSigHashNone sigHashSingle `shouldBe` False
+        isSigHashNone sigHashNone `shouldBe` True
+        isSigHashSingle sigHashAll `shouldBe` False
+        isSigHashSingle sigHashSingle `shouldBe` True
+        isSigHashUnknown sigHashAll `shouldBe` False
+        isSigHashUnknown sigHashNone `shouldBe` False
+        isSigHashUnknown sigHashSingle `shouldBe` False
+        isSigHashUnknown 0x00 `shouldBe` True
+        isSigHashUnknown 0x04 `shouldBe` True
+    it "can decodeTxSig . encode a TxSignature" $
+        property $
+        forAll (arbitraryTxSignature net) $ \(_, _, ts@(TxSignature _ sh)) ->
+            decodeTxSig net (encodeTxSig ts) `shouldBe` Right ts
+    it "can produce the sighash one" $
+        property $
+        forAll (arbitraryTx net) $ forAll arbitraryScript . testSigHashOne net
+
+testSigHashOne :: Network -> Tx -> Script -> Word64 -> Bool -> Property
+testSigHashOne net tx s val acp =
+    not (null $ txIn tx) ==>
+    if length (txIn tx) > length (txOut tx)
+        then res `shouldBe` one
+        else res `shouldNotBe` one
+  where
+    res = txSigHash net tx s val (length (txIn tx) - 1) (f sigHashSingle)
+    one = "0100000000000000000000000000000000000000000000000000000000000000"
+    f =
+        if acp
+            then setAnyoneCanPayFlag
+            else id
+
+{-- Test Utilities --}
+
+readTestFile :: A.FromJSON a => FilePath -> IO a
+readTestFile fp = do
+    bs <- BL.readFile $ "data/" <> fp <> ".json"
+    maybe (error $ "Could not read test file " <> fp) return $ A.decode bs
+
+{- Parse tests from bitcoin-qt repository -}
+
+type ParseError = String
+
+-- | Splits the JSON test into the different parts.  No processing,
+-- just handling the fact that comments may not be there or might have
+-- junk before it.  Output is the tuple ( sig, pubKey, flags, comment
+-- ) as strings
+testParts :: [String] -> Maybe (String, String, String, String)
+testParts l =
+    let (x, r) = splitAt 3 l
+        comment =
+            if null r
+                then ""
+                else last r
+    in if length x < 3
+           then Nothing
+           else let [sig, pubKey, flags] = x
+                in Just (sig, pubKey, flags, comment)
+
+-- | Maximum value of sequence number
+maxSeqNum :: Word32
+maxSeqNum = 0xffffffff -- Perhaps this should be moved to constants.
+
+-- | Some of the scripts tests require transactions be built in a
+-- standard way.  This function builds the crediting transaction.
+-- Quoting the top comment of script_valid.json: "It is evaluated as
+-- if there was a crediting coinbase transaction with two 0 pushes as
+-- scriptSig, and one output of 0 satoshi and given scriptPubKey,
+-- followed by a spending transaction which spends this output as only
+-- input (and correct prevout hash), using the given scriptSig. All
+-- nLockTimes are 0, all nSequences are max."
+buildCreditTx :: ByteString -> Tx
+buildCreditTx scriptPubKey =
+    Tx 1 [ txI ] [ txO ] [] 0
+  where
+    txO = TxOut { outValue = 0
+                , scriptOutput = scriptPubKey
+                }
+    txI = TxIn { prevOutput = nullOutPoint
+               , scriptInput = S.encode $ Script [ OP_0, OP_0 ]
+               , txInSequence = maxSeqNum
+               }
+
+-- | Build a spending transaction for the tests.  Takes as input the
+-- crediting transaction
+buildSpendTx :: ByteString  -- ScriptSig
+             -> Tx          -- Creditting Tx
+             -> Tx
+buildSpendTx scriptSig creditTx =
+    Tx 1 [ txI ] [ txO ] [] 0
+  where
+    txI = TxIn { prevOutput = OutPoint { outPointHash = txHash creditTx
+                                       , outPointIndex = 0
+                                       }
+               , scriptInput  = scriptSig
+               , txInSequence = maxSeqNum
+               }
+    txO = TxOut { outValue = 0, scriptOutput = BS.empty }
+
+mapMulSigVector :: ((Text, Text), Int) -> Spec
+mapMulSigVector (v, i) =
+    it name $ runMulSigVector v
+  where
+    name = "check multisig vector " <> show i
+
+runMulSigVector :: (Text, Text) -> Assertion
+runMulSigVector (a, ops) = assertBool "multisig vector" $ Just a == b
+  where
+    s = do
+        s <- decodeHex ops
+        eitherToMaybe $ S.decode s
+    b = do
+        o <- s
+        d <- eitherToMaybe $ decodeOutput o
+        addrToString $ p2shAddr btc d
+
+sigDecodeMap :: Network -> (Text, Int) -> Spec
+sigDecodeMap net (_, i) =
+    it ("check signature " ++ show i) func
+  where
+    func = testSigDecode net $ scriptSigSignatures !! i
+
+testSigDecode :: Network -> Text -> Assertion
+testSigDecode net str =
+    let bs = fromJust $ decodeHex str
+        eitherSig = decodeTxSig net bs
+    in assertBool
+           (unwords
+                [ "Decode failed:"
+                , fromLeft (error "Decode did not fail") eitherSig
+                ]) $
+       isRight eitherSig
+
+mulSigVectors :: [(Text, Text)]
+mulSigVectors =
+    [ ( "3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC"
+      , "52410491bba2510912a5bd37da1fb5b1673010e43d2c6d812c514e91bfa9f2eb129e1c183329db55bd868e209aac2fbc02cb33d98fe74bf23f0c235d6126b1d8334f864104865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac09ef122b1a986818a7cb624532f062c1d1f8722084861c5c3291ccffef4ec687441048d2455d2403e08708fc1f556002f1b6cd83f992d085097f9974ab08a28838f07896fbab08f39495e15fa6fad6edbfb1e754e35fa1c7844c41f322a1863d4621353ae"
+      )
+    ]
+
+scriptSigSignatures :: [Text]
+scriptSigSignatures =
+     -- Signature in input of txid 1983a69265920c24f89aac81942b1a59f7eb30821a8b3fb258f88882b6336053
+    [ "304402205ca6249f43538908151fe67b26d020306c0e59fa206cf9f3ccf641f33357119d02206c82f244d04ac0a48024fb9cc246b66e58598acf206139bdb7b75a2941a2b1e401"
+      -- Signature in input of txid
+      -- fb0a1d8d34fa5537e461ac384bac761125e1bfa7fec286fa72511240fa66864d.
+      -- Strange DER sizes, but in Blockchain. Now invalid as Haskoin can only
+      -- decode strict signatures.
+      -- "3048022200002b83d59c1d23c08efd82ee0662fec23309c3adbcbd1f0b8695378db4b14e736602220000334a96676e58b1bb01784cb7c556dd8ce1c220171904da22e18fe1e7d1510db501"
+    ]
+
+
+testID :: (FromJSON a, ToJSON a, Eq a) => a -> Bool
+testID x =
+    (A.decode . A.encode) (singleton ("object" :: String) x) ==
+    Just (singleton ("object" :: String) x)
diff --git a/test/Network/Haskoin/TransactionSpec.hs b/test/Network/Haskoin/TransactionSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/TransactionSpec.hs
@@ -0,0 +1,299 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Network.Haskoin.TransactionSpec (spec) where
+
+import           Control.Monad               (forM_, unless, zipWithM_)
+import           Control.Monad.IO.Class
+import           Data.Aeson                  as A
+import           Data.Aeson.Types            as A
+import           Data.ByteString             (ByteString)
+import qualified Data.ByteString             as BS
+import qualified Data.ByteString.Lazy        as BL
+import           Data.Either                 (fromLeft, fromRight, isLeft,
+                                              isRight)
+import           Data.List                   (groupBy)
+import           Data.Map.Strict             (singleton)
+import           Data.Maybe
+import           Data.Serialize              as S
+import           Data.Serialize.Get          (getWord32le, runGet)
+import           Data.Serialize.Put          (putWord32le, runPut)
+import           Data.String                 (fromString)
+import           Data.String.Conversions
+import           Data.Text                   (Text)
+import qualified Data.Vector                 as V
+import           Data.Word                   (Word32, Word64)
+import           GHC.Exts                    (IsString (..))
+import           Network.Haskoin.Address
+import           Network.Haskoin.Constants
+import           Network.Haskoin.Crypto
+import           Network.Haskoin.Keys
+import           Network.Haskoin.Script
+import           Network.Haskoin.Test
+import           Network.Haskoin.Transaction
+import           Network.Haskoin.Util
+import           Safe                        (readMay)
+import           Test.Hspec
+import           Test.HUnit                  (Assertion, assertBool,
+                                              assertFailure)
+import           Test.QuickCheck
+
+spec :: Spec
+spec = do
+    let net = btc
+    describe "transaction unit tests" $ do
+        it "compute txid from tx" $
+            zipWithM_ (curry mapTxIDVec) txIDVec [0 ..]
+        it "build pkhash transaction (generated from bitcoind)" $
+            zipWithM_ (curry mapPKHashVec) pkHashVec [0 ..]
+        it "encode satoshi core script pubkey" tEncodeSatoshiCoreScriptPubKey
+    describe "btc transaction" $ do
+        it "decode and encode txid" $
+            property $
+            forAll arbitraryTxHash $ \h -> hexToTxHash (txHashToHex h) == Just h
+        it "from string transaction id" $
+            property $
+            forAll arbitraryTxHash $ \h -> fromString (cs $ txHashToHex h) == h
+        it "building address tx" $
+            property $
+            forAll (arbitraryAddress net) $
+            forAll (arbitrarySatoshi net) . testBuildAddrTx net
+        it "guess transaction size" $
+            property $ forAll (arbitraryAddrOnlyTxFull net) (testGuessSize net)
+        it "choose coins" $
+            property $ forAll (listOf (arbitrarySatoshi net)) testChooseCoins
+        it "choose multisig coins" $
+            property $
+            forAll arbitraryMSParam $
+            forAll (listOf (arbitrarySatoshi net)) . testChooseMSCoins
+        it "sign and validate transaction" $
+            property $ forAll (arbitrarySigningData net) (testDetSignTx net)
+        it "merge partially signed transactions" $
+            property $ forAll (arbitraryPartialTxs net) (testMergeTx net)
+    describe "json serialization" $ do
+        it "encodes and decodes transaction" $
+            property $ forAll (arbitraryTx net) testID
+        it "encodes and decodes transaction hash" $
+            property $ forAll arbitraryTxHash testID
+    describe "transaction serialization" $ do
+        it "encodes and decodes tx input" $
+            property $ forAll (arbitraryTxIn net) cerealID
+        it "encodes and decodes tx output" $
+            property $ forAll (arbitraryTxOut net) cerealID
+        it "encodes and decodes outpoint" $
+            property $ forAll arbitraryOutPoint cerealID
+        it "encodes and decodes transaction" $
+            property $ forAll (arbitraryTx net) cerealID
+        it "encodes and decodes witness transaction" $
+            property $ forAll (arbitraryWitnessTx net) cerealID
+        it "encodes and decodes legacy transaction" $
+            property $ forAll (arbitraryLegacyTx net) cerealID
+
+cerealID :: (Serialize a, Eq a) => a -> Bool
+cerealID x = S.decode (S.encode x) == Right x
+
+mapTxIDVec :: ((Text, Text), Int) -> Assertion
+mapTxIDVec (v,i) = runTxIDVec v
+
+runTxIDVec :: (Text, Text) -> Assertion
+runTxIDVec (tid, tx) = assertBool "txid" $ txHashToHex (txHash txBS) == tid
+  where
+    txBS = fromJust $ either (const Nothing) return . S.decode =<< decodeHex tx
+
+txIDVec :: [(Text, Text)]
+txIDVec =
+    [ ( "23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"
+      , "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000"
+      )
+    , ( "c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"
+      , "01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000"
+      )
+    , ( "f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"
+      , "01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000"
+      )
+    , ( "afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae"
+      , "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000"
+      )
+    ]
+
+mapPKHashVec :: (([(Text, Word32)], [(Text, Word64)], Text), Int)
+            -> Assertion
+mapPKHashVec (v, i) = runPKHashVec v
+
+runPKHashVec :: ([(Text, Word32)], [(Text, Word64)], Text) -> Assertion
+runPKHashVec (xs, ys, res) =
+    assertBool "Build PKHash Tx" $ encodeHex (S.encode tx) == res
+  where
+    tx =
+        fromRight (error "Could not decode transaction") $
+        buildAddrTx btc (map f xs) ys
+    f (tid, ix) = OutPoint (fromJust $ hexToTxHash tid) ix
+
+-- These test vectors have been generated from bitcoind raw transaction api
+
+pkHashVec :: [([(Text, Word32)], [(Text, Word64)], Text)]
+pkHashVec =
+    [
+      ( [("eb29eba154166f6541ebcc9cbdf5088756e026af051f123bcfb526df594549db",14)]
+      , [("14LsRquZfURNFrzpcLVGdaHTfAPjjwiSPb",90000000)]
+      , "0100000001db494559df26b5cf3b121f05af26e0568708f5bd9ccceb41656f1654a1eb29eb0e00000000ffffffff01804a5d05000000001976a91424aa604689cc582292b97668bedd91dd5bf9374c88ac00000000"
+      )
+    , ( [ ("eb29eba154166f6541ebcc9cbdf5088756e026af051f123bcfb526df594549db",0)
+        , ("0001000000000000000000000000000000000000000000000000000000000000",2147483647)
+        ]
+      , [ ("14LsRquZfURNFrzpcLVGdaHTfAPjjwiSPb",1)
+        , ("19VCgS642vzEA1sdByoSn6GsWBwraV8D4n",2100000000000000)
+        ]
+      , "0100000002db494559df26b5cf3b121f05af26e0568708f5bd9ccceb41656f1654a1eb29eb0000000000ffffffff0000000000000000000000000000000000000000000000000000000000000100ffffff7f00ffffffff0201000000000000001976a91424aa604689cc582292b97668bedd91dd5bf9374c88ac0040075af07507001976a9145d16672f53981ff21c5f42b40d1954993cbca54f88ac00000000"
+      )
+    , ( [ ("eb29eba154166f6541ebcc9cbdf5088756e026af051f123bcfb526df594549db",0)
+        , ("0001000000000000000000000000000000000000000000000000000000000000",2147483647)
+        ]
+      , []
+      , "0100000002db494559df26b5cf3b121f05af26e0568708f5bd9ccceb41656f1654a1eb29eb0000000000ffffffff0000000000000000000000000000000000000000000000000000000000000100ffffff7f00ffffffff0000000000"
+      )
+    , ( []
+      , [ ("14LsRquZfURNFrzpcLVGdaHTfAPjjwiSPb",1)
+        , ("19VCgS642vzEA1sdByoSn6GsWBwraV8D4n",2100000000000000)
+        ]
+      , "01000000000201000000000000001976a91424aa604689cc582292b97668bedd91dd5bf9374c88ac0040075af07507001976a9145d16672f53981ff21c5f42b40d1954993cbca54f88ac00000000"
+      )
+    ]
+
+tEncodeSatoshiCoreScriptPubKey :: Assertion
+tEncodeSatoshiCoreScriptPubKey = assertBool "tEncodeSatoshiCoreScriptPubKey" $
+  t1BsOutputScriptPubKey == encodeSatoshiCoreScriptPubKey t1SatoshiCoreJsonScriptPubKey
+  where
+    t1BsOutputScriptPubKey :: Text
+    t1BsOutputScriptPubKey = "514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af52ae"
+    t1SatoshiCoreJsonScriptPubKey :: String
+    t1SatoshiCoreJsonScriptPubKey = "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"
+
+
+encodeSatoshiCoreScriptPubKey :: String -> Text
+encodeSatoshiCoreScriptPubKey =
+  mconcat . map encodeSatoshiCoreScriptPiece . words
+  where
+    encodeSatoshiCoreScriptPiece :: String -> Text
+    encodeSatoshiCoreScriptPiece s = case (readMay ("OP_" ++ s) :: Maybe ScriptOp) of
+      Just op -> encodeHex . S.encode $ op
+      Nothing -> case take 2 s of
+          "OP" -> encodeHex . S.encode . (read :: String -> ScriptOp) $ s
+          "0x" -> (fromString . drop 2 :: String -> Text) s
+          _ -> case (readMay s :: Maybe Int) of -- can we get rid of this case now?
+            Just i  -> encodeHex . S.encode . intToScriptOp $ i
+            Nothing -> error $ "encodeSatoshiCoreScriptPubKey: " ++ s
+
+type TestComment = String
+
+{- Building Transactions -}
+
+testBuildAddrTx :: Network -> Address -> TestCoin -> Bool
+testBuildAddrTx net a (TestCoin v) =
+    case a of
+        PubKeyAddress h net -> Right (PayPKHash h) == out
+        ScriptAddress h net -> Right (PayScriptHash h) == out
+  where
+    tx =
+        buildAddrTx
+            net
+            []
+            [ ( fromMaybe
+                    (error "Could not convert address to string")
+                    (addrToString a)
+              , v)
+            ]
+    out =
+        decodeOutputBS $
+        scriptOutput $
+        head $ txOut (fromRight (error "Could not build transaction") tx)
+
+testGuessSize :: Network -> Tx -> Bool
+testGuessSize net tx
+    -- We compute an upper bound but it should be close enough to the real size
+    -- We give 2 bytes of slack on every signature (1 on r and 1 on s)
+ = guess >= len && guess <= len + 2 * delta
+  where
+    delta = pki + sum (map fst msi)
+    guess = guessTxSize pki msi pkout msout
+    len = BS.length $ S.encode tx
+    ins = map f $ txIn tx
+    f i =
+        fromRight (error "Could not decode input") $
+        decodeInputBS net $ scriptInput i
+    pki = length $ filter isSpendPKHash ins
+    msi = concatMap shData ins
+    shData (ScriptHashInput _ (PayMulSig keys r)) = [(r, length keys)]
+    shData _                                      = []
+    out =
+        map
+            (fromRight (error "Could not decode transaction output") .
+             decodeOutputBS . scriptOutput) $
+        txOut tx
+    pkout = length $ filter isPayPKHash out
+    msout = length $ filter isPayScriptHash out
+
+testChooseCoins :: [TestCoin] -> Word64 -> Word64 -> Int -> Property
+testChooseCoins coins target byteFee nOut = nOut >= 0 ==>
+    case chooseCoins target byteFee nOut True coins of
+        Right (chosen, change) ->
+            let outSum = sum $ map coinValue chosen
+                fee    = guessTxFee byteFee nOut (length chosen)
+            in outSum == target + change + fee
+        Left _ ->
+            let fee = guessTxFee byteFee nOut (length coins)
+            in target == 0 || s < target + fee
+  where
+    s  = sum $ map coinValue coins
+
+testChooseMSCoins :: (Int, Int) -> [TestCoin]
+                  -> Word64 -> Word64 -> Int -> Property
+testChooseMSCoins (m, n) coins target byteFee nOut = nOut >= 0 ==>
+    case chooseMSCoins target byteFee (m,n) nOut True coins of
+        Right (chosen,change) ->
+            let outSum = sum $ map coinValue chosen
+                fee    = guessMSTxFee byteFee (m,n) nOut (length chosen)
+            in outSum == target + change + fee
+        Left _ ->
+            let fee = guessMSTxFee byteFee (m,n) nOut (length coins)
+            in target == 0 || s < target + fee
+  where
+    s = sum $ map coinValue coins
+
+{- Signing Transactions -}
+
+testDetSignTx :: Network -> (Tx, [SigInput], [SecKeyI]) -> Bool
+testDetSignTx net  (tx, sigis, prv) =
+    not (verifyStdTx net tx verData) &&
+    not (verifyStdTx net txSigP verData) && verifyStdTx net txSigC verData
+  where
+    txSigP =
+        fromRight (error "Could not decode transaction") $
+        signTx net tx sigis (tail prv)
+    txSigC =
+        fromRight (error "Could not decode transaction") $
+        signTx net txSigP sigis [head prv]
+    verData = map (\(SigInput s v o _ _) -> (s, v, o)) sigis
+
+testMergeTx :: Network -> ([Tx], [(ScriptOutput, Word64, OutPoint, Int, Int)]) -> Bool
+testMergeTx net (txs, os) = and
+    [ isRight mergeRes
+    , length (txIn mergedTx) == length os
+    , if enoughSigs then isValid else not isValid
+    -- Signature count == min (length txs) (sum required signatures)
+    , sum (map snd sigMap) == min (length txs) (sum (map fst sigMap))
+    ]
+  where
+    outs = map (\(so, val, op, _, _) -> (so, val, op)) os
+    mergeRes = mergeTxs net txs outs
+    mergedTx = fromRight (error "Could not merge") mergeRes
+    isValid = verifyStdTx net mergedTx outs
+    enoughSigs = all (\(m,c) -> c >= m) sigMap
+    sigMap = map (\((_,_,_,m,_), inp) -> (m, sigCnt inp)) $ zip os $ txIn mergedTx
+    sigCnt inp = case decodeInputBS net $ scriptInput inp of
+        Right (RegularInput (SpendMulSig sigs)) -> length sigs
+        Right (ScriptHashInput (SpendMulSig sigs) _) -> length sigs
+        _ -> error "Invalid input script type"
+
+testID :: (FromJSON a, ToJSON a, Eq a) => a -> Bool
+testID x =
+    (A.decode . A.encode) (singleton ("object" :: String) x) ==
+    Just (singleton ("object" :: String) x)
diff --git a/test/Network/Haskoin/UtilSpec.hs b/test/Network/Haskoin/UtilSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Haskoin/UtilSpec.hs
@@ -0,0 +1,64 @@
+module Network.Haskoin.UtilSpec (spec) where
+
+import qualified Data.ByteString      as BS
+import           Data.Either          (fromLeft, fromRight, isLeft, isRight)
+import           Data.Foldable        (toList)
+import           Data.List            (permutations)
+import           Data.Maybe
+import qualified Data.Sequence        as Seq
+import           Network.Haskoin.Test
+import           Network.Haskoin.Util
+import           Test.Hspec
+import           Test.QuickCheck
+
+spec :: Spec
+spec =
+    describe "utility functions" $ do
+        it "bsToInteger . integerToBS" $ property getPutInteger
+        it "decodeHex . encodeHex" $ property $ forAll arbitraryBS fromToHex
+        it "compare updateIndex with Data.Sequence" $ property testUpdateIndex
+        it "matchTemplate" $ property testMatchTemplate
+        it "testing matchTemplate with two lists" $
+            property testMatchTemplateLen
+        it "either helper functions" $ property testEither
+
+{- Various utilities -}
+
+getPutInteger :: Integer -> Bool
+getPutInteger i = bsToInteger (integerToBS $ abs i) == abs i
+
+fromToHex :: BS.ByteString -> Bool
+fromToHex bs = decodeHex (encodeHex bs) == Just bs
+
+testUpdateIndex :: [Int] -> Int -> Int -> Bool
+testUpdateIndex xs v i =
+    updateIndex i xs (const v) == toList (Seq.update i v $ Seq.fromList xs)
+
+testMatchTemplate :: [Int] -> Int -> Bool
+testMatchTemplate as i = catMaybes res == bs
+  where
+    res = matchTemplate as bs (==)
+    idx =
+        if null as
+            then 0
+            else i `mod` length as
+    bs = permutations as !! idx
+
+testMatchTemplateLen :: [Int] -> [Int] -> Bool
+testMatchTemplateLen as bs = length bs == length res
+  where
+    res = matchTemplate as bs (==)
+
+testEither :: Either String Int -> Bool
+testEither e =
+    case e of
+        (Right v) ->
+            isRight e &&
+            not (isLeft e) &&
+            fromRight (error "Unexpected Left") e == v &&
+            eitherToMaybe e == Just v
+        (Left v) ->
+            isLeft e &&
+            not (isRight e) &&
+            fromLeft (error "Unexpected Right") e == v &&
+            isNothing (eitherToMaybe e)
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
diff --git a/tests/Main.hs b/tests/Main.hs
deleted file mode 100644
--- a/tests/Main.hs
+++ /dev/null
@@ -1,69 +0,0 @@
-module Main where
-
-import Test.Framework (defaultMain)
-
--- Util tests
-import qualified Network.Haskoin.Util.Tests (tests)
-
--- Crypto tests
-import qualified Network.Haskoin.Crypto.ECDSA.Tests (tests)
-import qualified Network.Haskoin.Crypto.Base58.Tests (tests)
-import qualified Network.Haskoin.Crypto.Base58.Units (tests)
-import qualified Network.Haskoin.Crypto.Keys.Tests (tests)
-import qualified Network.Haskoin.Crypto.ExtendedKeys.Tests (tests)
-import qualified Network.Haskoin.Crypto.ExtendedKeys.Units (tests)
-import qualified Network.Haskoin.Crypto.Hash.Tests (tests)
-import qualified Network.Haskoin.Crypto.Hash.Units (tests)
-import qualified Network.Haskoin.Crypto.Mnemonic.Tests (tests)
-import qualified Network.Haskoin.Crypto.Mnemonic.Units (tests)
-import qualified Network.Haskoin.Crypto.Units (tests)
-
--- Node tests
-import qualified Network.Haskoin.Node.Units (tests)
-
--- Script tests
-import qualified Network.Haskoin.Script.Tests (tests)
-import qualified Network.Haskoin.Script.Units (tests)
-
--- Transaction tests
-import qualified Network.Haskoin.Transaction.Tests (tests)
-import qualified Network.Haskoin.Transaction.Units (tests, satoshiCoreTxTests)
-
--- Block tests
-import qualified Network.Haskoin.Block.Tests (tests)
-import qualified Network.Haskoin.Block.Units (tests)
-
--- Json tests
-import qualified Network.Haskoin.Json.Tests (tests)
-
--- Binary tests
-import qualified Network.Haskoin.Cereal.Tests (tests)
-
-main :: IO ()
-main = do
-  satoshiTxTests <- Network.Haskoin.Transaction.Units.satoshiCoreTxTests
-  defaultMain
-    (  Network.Haskoin.Json.Tests.tests
-    ++ Network.Haskoin.Cereal.Tests.tests
-    ++ Network.Haskoin.Util.Tests.tests
-    ++ Network.Haskoin.Crypto.ECDSA.Tests.tests
-    ++ Network.Haskoin.Crypto.Base58.Tests.tests
-    ++ Network.Haskoin.Crypto.Base58.Units.tests
-    ++ Network.Haskoin.Crypto.Hash.Tests.tests
-    ++ Network.Haskoin.Crypto.Hash.Units.tests
-    ++ Network.Haskoin.Crypto.Keys.Tests.tests
-    ++ Network.Haskoin.Crypto.ExtendedKeys.Tests.tests
-    ++ Network.Haskoin.Crypto.ExtendedKeys.Units.tests
-    ++ Network.Haskoin.Crypto.Mnemonic.Tests.tests
-    ++ Network.Haskoin.Crypto.Mnemonic.Units.tests
-    ++ Network.Haskoin.Crypto.Units.tests
-    ++ Network.Haskoin.Node.Units.tests
-    ++ Network.Haskoin.Script.Tests.tests
-    ++ Network.Haskoin.Script.Units.tests
-    ++ Network.Haskoin.Transaction.Tests.tests
-    ++ Network.Haskoin.Transaction.Units.tests
-    ++ satoshiTxTests
-    ++ Network.Haskoin.Block.Tests.tests
-    ++ Network.Haskoin.Block.Units.tests
-    )
-
diff --git a/tests/Network/Haskoin/Block/Tests.hs b/tests/Network/Haskoin/Block/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Block/Tests.hs
+++ /dev/null
@@ -1,63 +0,0 @@
-module Network.Haskoin.Block.Tests (tests) where
-
-import Control.Arrow
-
-import Data.String (fromString)
-import Data.String.Conversions (cs)
-import Test.QuickCheck (Property, (==>))
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.Maybe (fromJust)
-
-import Network.Haskoin.Block
-import Network.Haskoin.Util
-import Network.Haskoin.Test
-
-tests :: [Test]
-tests =
-    [ testGroup "Block tests"
-        [ testProperty "decode . encode BlockHash id" decEncBlockHashid ]
-    , testGroup "Merkle trees"
-        [ testProperty "Width of tree at maxmum height = 1" testTreeWidth
-        , testProperty "Width of tree at height 0 is # txns" testBaseWidth
-        , testProperty "extract . build partial merkle tree" buildExtractTree
-        ]
-    , testGroup "Block hashes"
-        [ testProperty "Read/Show block hash" testReadShowBlockHash
-        , testProperty "From string block hash" fromStringBlockHash
-        ]
-    ]
-
-decEncBlockHashid :: ArbitraryBlockHash -> Bool
-decEncBlockHashid (ArbitraryBlockHash h) =
-    fromJust (hexToBlockHash $ blockHashToHex h) == h
-
-{- Merkle Trees -}
-
-testTreeWidth :: Int -> Property
-testTreeWidth i = i /= 0 ==>
-    calcTreeWidth i' (calcTreeHeight i') == 1
-  where
-    i' = abs i
-
-testBaseWidth :: Int -> Property
-testBaseWidth i = i /= 0 ==>
-    calcTreeWidth i' 0 == i'
-  where
-    i' = abs i
-
-buildExtractTree :: [(ArbitraryTxHash, Bool)] -> Property
-buildExtractTree txs = not (null txs) ==>
-    r == (buildMerkleRoot hashes) && m == (map (txh . fst) $ filter snd txs)
-  where
-    (f, h) = buildPartialMerkle $ map (first txh) txs
-    (r, m) = fromRight $ extractMatches f h (length txs)
-    hashes = map (txh . fst) txs
-    txh (ArbitraryTxHash t) = t
-
-testReadShowBlockHash :: ArbitraryBlockHash -> Bool
-testReadShowBlockHash (ArbitraryBlockHash h) = read (show h) == h
-
-fromStringBlockHash :: ArbitraryBlockHash -> Bool
-fromStringBlockHash (ArbitraryBlockHash h) = fromString (cs $ blockHashToHex h) == h
diff --git a/tests/Network/Haskoin/Block/Units.hs b/tests/Network/Haskoin/Block/Units.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Block/Units.hs
+++ /dev/null
@@ -1,116 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Network.Haskoin.Block.Units (tests) where
-
-import Data.ByteString (ByteString)
-
-import Test.HUnit (Assertion, assertBool)
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-
-import Data.Maybe (fromJust)
-
-import Network.Haskoin.Block
-import Network.Haskoin.Transaction
-
-tests :: [Test]
-tests =
-    [ testGroup "Merkle Roots"
-        (map mapMerkleVectors $ zip merkleVectors [0..])
-    ]
-
-mapMerkleVectors :: ((ByteString, [ByteString]), Int) -> Test.Framework.Test
-mapMerkleVectors (v, i) =
-    testCase name $ runMerkleVector v
-  where
-    name = "MerkleRoot vector " ++ (show i)
-
-runMerkleVector :: (ByteString, [ByteString]) -> Assertion
-runMerkleVector (r, hs) = do
-    assertBool "    >  Merkle Vector" $
-        buildMerkleRoot (map f hs) == getTxHash (f r)
-  where
-    f = fromJust . hexToTxHash
-
-merkleVectors :: [(ByteString, [ByteString])]
-merkleVectors =
-      -- Block 000000000000cd7e8cf6510303dde76121a1a791c15dba0be4be7022b07cf9e1
-    [ ( "fb6698ac95b754256c5e71b4fbe07638cb6ca83ee67f44e181b91727f09f4b1f"
-      , [ "dd96fdcfaec994bf583af650ff6022980ee0ba1686d84d0a3a2d24eabf34bc52"
-        , "1bc216f786a564378710ae589916fc8e092ddfb9f24fe6c47b733550d476d5d9"
-        , "a1db0b0194426064b067899ff2d975fb277fd52dbb1a38370800c76dd6503d41"
-        , "d69f7fb0e668fbd437d1bf5211cc34d7eb8746f50cfddf705fe10bc2f8f7035f"
-        , "5b4057cd80be7df5ed2ac42b776897ed3c26e3a01e4072075b8129c587094ef6"
-        , "ed6dabcfba0ef43c50d89a8a0e4b236b1bc6585d4c3bbf49728b55f44312d6bc"
-        , "056aaa9a3c635909c794e9b0acc7dccb0456c59a84c6b08417335bee4515e3d3"
-        , "05bae5f1d1c874171692e1fc06f664e63eb143d3f096601ef938e4a9012eee66"
-        , "b5e48e94e3f2fba197b3f591e01f47e185d7834d669529d44078e41c671aab0f"
-        , "3b56aeadfc0c5484fd507bc89f13f2e5f61c42e0a4ae9062eda9a9aeef7db6a4"
-        , "2affa187e1ebb94a2a86578b9f64951e854ff3d346fef259acfb6d0f5212e0d3"
-        ]
-      )
-      -- Block 00000000000007cc4b6f07bfed72bccc1ed8dd031a93969a4c22211f784457d4
-    , ( "886fea311d2dc64c315519f2d647e43998d780d2170f77e53dc0d85bf2ee680c"
-      , [ "c9c9e5211512629fd111cc071d745b8c79bf486b4ea95489eb5de08b5d786b8e"
-        , "20beb0ee30dfd323ade790ce9a46ae7a174f9ea44ce22a17c4d4eb23b7016f51"
-        , "d4cb7dd741e78a8f57e12f6c8ddb0361ff2a5bf9365bd7d7df761060847daf9a"
-        , "ddbfa6fdd29d4b47aeaadf82a4bf0a93d58cd7d8401fabf860a1ae8eeb51f42e"
-        , "9d82bafe44abee248b968c86f165051c8413482c232659795335c52922dab471"
-        , "86035372d31b53efd848cea7231aa9738c209aff64d3c59b1619341afb5b6ba3"
-        , "11e7a7393d9658813dfaebc04fa6d4b73bac8d641bffa7067da879523d43d030"
-        , "2f676b9aa5bc0ebf3395032c84c466e40cac29f80434cd1138e31c2d0fcc5c13"
-        , "37567d559fbfae07fda9a90de0ce30b202128bc8ebdfef5ad2b53e865a3478c2"
-        , "0b8e6c1200c454361e94e261738429e9c9b8dcffd85ec8511bbf5dc7e2e0ada8"
-        ]
-      )
-      -- Block 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
-    , ( "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
-      , [ "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098" ]
-      )
-      -- Block 000000000004d160ac1f7b775d7c1823345aeadd5fcb29ca2ad2403bb7babd4c
-    , ( "aae018650f513fc42d55b2210ec3ceeeb194fb1261d37989de07451fc0cbac5c"
-      , [ "a4454f22831acd7904a9902c5070a3ee4bf4c2b13bc6b2dc66735dd3c4414028"
-        , "45297f334278885108dd38a0b689ed95a4373dd3f7e4413e6aebdc2654fb771b"
-        ]
-      )
-      -- Block 000000000001d1b13a7e86ddb20da178f20d6da5cd037a29c2a15b8b84cc774e
-    , ( "ca3580505feb87544760ac14a5859659e23be05f765bbed9f86a3c9aad1a5d0c"
-      , [ "60702384c6e9d34ff03c2b3e726bdc649befe603216815bd0a2974921d0d9549"
-        , "11f40f58941d2a81a1616a3b84b7dd8b9d07e68750827de488c11a18f54220bb"
-        , "d78e82527aa8cf16e375010bc666362c0258d3c0da1885a1871121706da8b633"
-        ]
-      )
-      -- Block 0000000000000630a4e2266a31776e952a19b7c99a6387917d9de9032f608021
-    , ( "dcce8be0a9a41e7bb726c5b49d957d90b5308e3dc5dce070ccbc8996e265a6c2"
-      , [ "c0f58ff12cd1023b05f8f7035cc62bf50958ddb216a4e0eb5471deb7ef25fe81"
-        , "24e5bbf9008641b8fcf3d076fef66c28c695362ba9f6a6042f8275a98414ee92"
-        , "e8e1f72abad5e34dabc0f6de46a484b17a9af857d1c41de19482fadf6f7f4b27"
-        , "540e4d34d9fd9e5ec02853054be7ad9260379bc23388489049cca1b0f7cf518a"
-        , "324444835c5fe0545f98c4240011b75e6ea1bb76f41829e4cfbe7f75b6cee924"
-        , "e7d31437ac21bceb0c222a82b2723e2b8a7654147e33397679f041537022a4b2"
-        , "a8b5768d8b33525ee89d546a6a6897f8e42ba9d56a2c5e871a5d2ab40258dc95"
-        , "7ba712b31bae8d45810a5cda3838c7e7fb9abd6e88bb4b3ee79be9ea2f714bb4"
-        , "2ae1c4d927b06edaa626b230976ad8062bbae24da9378d1de2409da5ab08a26d"
-        , "3c417dc8087d6878003624b74431e17fec9ca761389034b1b1e0f32cbfb11f4f"
-        , "de6de7beae8d8c98c7d46b4409d5460e58e3204d8b4caed256c7471998595909"
-        , "c7c3c211402b7c4379f7b01fadc67260ee58d11e8d0bcce3d68cb45f3467e99d"
-        , "77aa2717e727a096d81074bd46ae59462692d20a1acc1a01b2535518ae5aeb53"
-        , "4859a710bb673aca46208bbd59d1000ae990dafff5f70b56f0853aeeaea3948b"
-        , "38deca6991988e461b83aa0d49ffef0f304c4b760371682d152eeb8c56a48174"
-        , "648f4f50dada3574e2dfe2dc68956b01dd97d543859a3540bbe1ef5418d0e494"
-        , "9cd7be42c2f0cd8bf38738c162cd05108e213ec7958bf2571cb627872963f5c4"
-        , "6740e0dd8b97e23864af41839fc197238d2f0dbefce9a82c657556be65c465fa"
-        , "f75c2e4b70db4b0aabc44b77af1ae75d305340fcf6e7b5f806ddcba4aa42b55d"
-        , "e125c488636749da68e6696b97525a77146c0777c7946927e37afd513d74a4e6"
-        , "c20526f119aea10880af631eba7f0b60385a22e0b0c402fe8508d41952e58be9"
-        , "6456c023c7e245f5c57a168633a23f57f4fadb651115f807694a6bed14ae3b55"
-        , "98b26e364e2888c9f264e4b5e13103c89608609774eb07ce933d8a2a45d19776"
-        , "2efaa4f167bb65ba5684f8076cd9279fd67fd9c67388c8862809bab5542e637d"
-        , "ec44eeb84d8d976d77079a822710b4dfdb11a2d9a03d8cc00bab0ae424e84666"
-        , "410730d9f807d81ac48b8eafac6f1d36642c1c370241b367a35f0bac6ac7c05f"
-        , "e95a7d0d477fd3db22756a3fd390a50c7bc48dc9e946fea9d24bd0866b3bb0e9"
-        , "a72fec99d14939216628aaf7a0afc4c017113bcae964e777e6b508864eeaacc4"
-        , "8548433310fcf75dbbc042121e8318c678e0a017534786dd322a91cebe8d213f"
-        ]
-      )
-    ]
-
diff --git a/tests/Network/Haskoin/Cereal/Tests.hs b/tests/Network/Haskoin/Cereal/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Cereal/Tests.hs
+++ /dev/null
@@ -1,72 +0,0 @@
-module Network.Haskoin.Cereal.Tests (tests) where
-
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.Serialize (Serialize, decode, encode)
-
-import Network.Haskoin.Test
-
-tests :: [Test]
-tests =
-    [ testGroup "Binary encoding and decoding of utility types"
-        [ testProperty "ByteString" $ \(ArbitraryByteString x) -> metaBinary x ]
-    , testGroup "Binary encoding and decoding of hash types"
-        [ testProperty "Hash160" $ \(ArbitraryHash160 x) -> metaBinary x
-        , testProperty "Hash256" $ \(ArbitraryHash256 x) -> metaBinary x
-        , testProperty "Hash512" $ \(ArbitraryHash512 x) -> metaBinary x
-        ]
-    , testGroup "Binary encoding and decoding of crypto types"
-        [ testProperty "Signature" $ \(ArbitrarySignature _ _ x) -> metaBinary x
-        , testProperty "PubKey" $ \(ArbitraryPubKey _ x) -> metaBinary x
-        , testProperty "XPrvKey" $ \(ArbitraryXPrvKey x) -> metaBinary x
-        , testProperty "XPubKey" $ \(ArbitraryXPubKey _ x) -> metaBinary x
-        ]
-    , testGroup "Binary encoding and decoding of protocol types"
-        [ testProperty "VarInt" $ \(ArbitraryVarInt x) -> metaBinary x
-        , testProperty "VarString" $ \(ArbitraryVarString x) -> metaBinary x
-        , testProperty "NetworkAddress" $ \(ArbitraryNetworkAddress x) -> metaBinary x
-        , testProperty "InvType" $ \(ArbitraryInvType x) -> metaBinary x
-        , testProperty "InvVector" $ \(ArbitraryInvVector x) -> metaBinary x
-        , testProperty "Inv" $ \(ArbitraryInv x) -> metaBinary x
-        , testProperty "Version" $ \(ArbitraryVersion x) -> metaBinary x
-        , testProperty "Addr" $ \(ArbitraryAddr x) -> metaBinary x
-        , testProperty "Alert" $ \(ArbitraryAlert x) -> metaBinary x
-        , testProperty "Reject" $ \(ArbitraryReject x) -> metaBinary x
-        , testProperty "GetData" $ \(ArbitraryGetData x) -> metaBinary x
-        , testProperty "NotFound" $ \(ArbitraryNotFound x) -> metaBinary x
-        , testProperty "Ping" $ \(ArbitraryPing x) -> metaBinary x
-        , testProperty "Pong" $ \(ArbitraryPong x) -> metaBinary x
-        , testProperty "MessageCommand" $ \(ArbitraryMessageCommand x) -> metaBinary x
-        , testProperty "MessageHeader" $ \(ArbitraryMessageHeader x) -> metaBinary x
-        , testProperty "Message" $ \(ArbitraryMessage x) -> metaBinary x
-        ]
-    , testGroup "Binary encoding and decoding of script types"
-        [ testProperty "ScriptOp" $ \(ArbitraryScriptOp x) -> metaBinary x
-        , testProperty "Script" $ \(ArbitraryScript x) -> metaBinary x
-        , testProperty "SigHash" $ \(ArbitrarySigHash x) -> metaBinary x
-        ]
-    , testGroup "Binary encoding and decoding of transaction types"
-        [ testProperty "TxIn" $ \(ArbitraryTxIn x) -> metaBinary x
-        , testProperty "TxOut" $ \(ArbitraryTxOut x) -> metaBinary x
-        , testProperty "OutPoint" $ \(ArbitraryOutPoint x) -> metaBinary x
-        , testProperty "Tx" $ \(ArbitraryTx x) -> metaBinary x
-        ]
-    , testGroup "Binary encoding and decoding of block types"
-        [ testProperty "Block" $ \(ArbitraryBlock x) -> metaBinary x
-        , testProperty "BlockHeader" $ \(ArbitraryBlockHeader x) -> metaBinary x
-        , testProperty "GetBlocks" $ \(ArbitraryGetBlocks x) -> metaBinary x
-        , testProperty "GetHeaders" $ \(ArbitraryGetHeaders x) -> metaBinary x
-        , testProperty "Headers" $ \(ArbitraryHeaders x) -> metaBinary x
-        , testProperty "MerkleBlock" $ \(ArbitraryMerkleBlock x) -> metaBinary x
-        ]
-    , testGroup "Binary encoding and decoding of bloom types"
-        [ testProperty "BloomFlags" $ \(ArbitraryBloomFlags x) -> metaBinary x
-        , testProperty "BloomFilter" $ \(ArbitraryBloomFilter _ _ x) -> metaBinary x
-        , testProperty "FilterLoad" $ \(ArbitraryFilterLoad x) -> metaBinary x
-        , testProperty "FilterAdd" $ \(ArbitraryFilterAdd x) -> metaBinary x
-        ]
-    ]
-
-metaBinary :: (Serialize a, Eq a) => a -> Bool
-metaBinary x = decode (encode x) == Right x
diff --git a/tests/Network/Haskoin/Crypto/Base58/Tests.hs b/tests/Network/Haskoin/Crypto/Base58/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/Base58/Tests.hs
+++ /dev/null
@@ -1,39 +0,0 @@
-module Network.Haskoin.Crypto.Base58.Tests (tests) where
-
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.String (fromString)
-import Data.String.Conversions (cs)
-
-import Network.Haskoin.Test
-import Network.Haskoin.Crypto
-
-tests :: [Test]
-tests =
-    [ testGroup "Address and Base58"
-        [ testProperty "decode58( encode58(i) ) = i" decodeEncode58
-        , testProperty "decode58Chk( encode58Chk(i) ) = i" decodeEncode58Check
-        , testProperty "decode58( encode58(address) ) = address" decEncAddr
-        , testProperty "Read/Show address" testReadShowAddress
-        , testProperty "From string address" testFromStringAddress
-        ]
-    ]
-
-decodeEncode58 :: ArbitraryByteString -> Bool
-decodeEncode58 (ArbitraryByteString bs) =
-    decodeBase58 (encodeBase58 bs) == Just bs
-
-decodeEncode58Check :: ArbitraryByteString -> Bool
-decodeEncode58Check (ArbitraryByteString bs) =
-    decodeBase58Check (encodeBase58Check bs) == Just bs
-
-decEncAddr :: ArbitraryAddress -> Bool
-decEncAddr (ArbitraryAddress a) = base58ToAddr (addrToBase58 a) == Just a
-
-
-testReadShowAddress :: ArbitraryAddress -> Bool
-testReadShowAddress (ArbitraryAddress a) = read (show a) == a
-
-testFromStringAddress :: ArbitraryAddress -> Bool
-testFromStringAddress (ArbitraryAddress a) = fromString (cs $ addrToBase58 a) == a
diff --git a/tests/Network/Haskoin/Crypto/Base58/Units.hs b/tests/Network/Haskoin/Crypto/Base58/Units.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/Base58/Units.hs
+++ /dev/null
@@ -1,45 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Network.Haskoin.Crypto.Base58.Units (tests) where
-
-import Test.HUnit (Assertion, assertBool)
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as BS (append, pack, empty)
-
-import Network.Haskoin.Crypto
-
-tests :: [Test]
-tests =
-    [ testGroup "Test base58 encodings"
-        ( map mapBase58Vec $ zip vectors [0..] )
-    ]
-
-mapBase58Vec :: ((ByteString, ByteString, ByteString), Int) -> Test.Framework.Test
-mapBase58Vec (v, i) =
-    testCase (unwords [ "Test base58 vector", show i ]) $ runVector v
-
-runVector :: (ByteString, ByteString, ByteString) -> Assertion
-runVector (bs, e, chk) = do
-    assertBool "encodeBase58" $ e == b58
-    assertBool "encodeBase58Check" $ chk == b58Chk
-    assertBool "decodeBase58" $ Just bs == decodeBase58 b58
-    assertBool "decodeBase58Check" $ Just bs == decodeBase58Check b58Chk
-  where
-    b58    = encodeBase58 bs
-    b58Chk = encodeBase58Check bs
-
-vectors :: [(ByteString, ByteString, ByteString)]
-vectors =
-    [ ( BS.empty, "", "3QJmnh" )
-    , ( BS.pack [0], "1", "1Wh4bh" )
-    , ( BS.pack [0,0,0,0], "1111", "11114bdQda" )
-    , ( BS.pack [0,0,1,0,0], "11LUw", "113CUwsFVuo" )
-    , ( BS.pack [255], "5Q", "VrZDWwe" )
-    , ( BS.pack [0,0,0,0] `BS.append` BS.pack [1..255]
-      , "1111cWB5HCBdLjAuqGGReWE3R3CguuwSjw6RHn39s2yuDRTS5NsBgNiFpWgAnEx6VQi8csexkgYw3mdYrMHr8x9i7aEwP8kZ7vccXWqKDvGv3u1GxFKPuAkn8JCPPGDMf3vMMnbzm6Nh9zh1gcNsMvH3ZNLmP5fSG6DGbbi2tuwMWPthr4boWwCxf7ewSgNQeacyozhKDDQQ1qL5fQFUW52QKUZDZ5fw3KXNQJMcNTcaB723LchjeKun7MuGW5qyCBZYzA1KjofN1gYBV3NqyhQJ3Ns746GNuf9N2pQPmHz4xpnSrrfCvy6TVVz5d4PdrjeshsWQwpZsZGzvbdAdN8MKV5QsBDY"
-      , "111151KWPPBRzdWPr1ASeu172gVgLf1YfUp6VJyk6K9t4cLqYtFHcMa2iX8S3NJEprUcW7W5LvaPRpz7UG7puBj5STE3nKhCGt5eckYq7mMn5nT7oTTic2BAX6zDdqrmGCnkszQkzkz8e5QLGDjf7KeQgtEDm4UER6DMSdBjFQVa6cHrrJn9myVyyhUrsVnfUk2WmNFZvkWv3Tnvzo2cJ1xW62XDfUgYz1pd97eUGGPuXvDFfLsBVd1dfdUhPwxW7pMPgdWHTmg5uqKGFF6vE4xXpAqZTbTxRZjCDdTn68c2wrcxApm8hq3JX65Hix7VtcD13FF8b7BzBtwjXq1ze6NMjKgUcqpJTN9vt"
-      )
-    ]
-
diff --git a/tests/Network/Haskoin/Crypto/ECDSA/Tests.hs b/tests/Network/Haskoin/Crypto/ECDSA/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/ECDSA/Tests.hs
+++ /dev/null
@@ -1,81 +0,0 @@
-module Network.Haskoin.Crypto.ECDSA.Tests (tests) where
-
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.Bits (testBit)
-import qualified Data.ByteString as BS (index, length)
-import Data.Serialize (encode)
-
-import Network.Haskoin.Test
-import Network.Haskoin.Crypto
-
-tests :: [Test]
-tests =
-    [ testGroup "ECDSA signatures"
-        [ testProperty "Verify signature" testVerifySig
-        , testProperty "S component <= order/2" $
-            \(ArbitrarySignature _ _ sig) -> halfOrderSig sig
-        ]
-    , testGroup "ECDSA Binary"
-        [ testProperty "Encoded signature is canonical" $
-            \(ArbitrarySignature _ _ sig) -> testIsCanonical sig
-        ]
-    ]
-
-{- ECDSA Signatures -}
-
-halfOrderSig :: Signature -> Bool
-halfOrderSig = isCanonicalHalfOrder
-
-testVerifySig :: ArbitrarySignature -> Bool
-testVerifySig (ArbitrarySignature msg key sig) =
-    verifySig msg sig pubkey
-  where
-    pubkey = derivePubKey key
-
-{- ECDSA Binary -}
-
--- github.com/bitcoin/bitcoin/blob/master/src/script.cpp
--- from function IsCanonicalSignature
-testIsCanonical :: Signature -> Bool
-testIsCanonical sig = not $
-    -- Non-canonical signature: too short
-    (len < 8) ||
-    -- Non-canonical signature: too long
-    (len > 72) ||
-    -- Non-canonical signature: wrong type
-    (BS.index s 0 /= 0x30) ||
-    -- Non-canonical signature: wrong length marker
-    (BS.index s 1 /= len - 2) ||
-    -- Non-canonical signature: S length misplaced
-    (5 + rlen >= len) ||
-    -- Non-canonical signature: R+S length mismatch
-    (rlen + slen + 6 /= len) ||
-    -- Non-canonical signature: R value type mismatch
-    (BS.index s 2 /= 0x02) ||
-    -- Non-canonical signature: R length is zero
-    (rlen == 0) ||
-    -- Non-canonical signature: R value negative
-    (testBit (BS.index s 4) 7) ||
-    -- Non-canonical signature: R value excessively padded
-    (  rlen > 1
-    && BS.index s 4 == 0
-    && not (testBit (BS.index s 5) 7)
-    ) ||
-    -- Non-canonical signature: S value type mismatch
-    (BS.index s (fromIntegral rlen+4) /= 0x02) ||
-    -- Non-canonical signature: S length is zero
-    (slen == 0) ||
-    -- Non-canonical signature: S value negative
-    (testBit (BS.index s (fromIntegral rlen+6)) 7) ||
-    -- Non-canonical signature: S value excessively padded
-    (  slen > 1
-    && BS.index s (fromIntegral rlen+6) == 0
-    && not (testBit (BS.index s (fromIntegral rlen+7)) 7)
-    )
-  where
-    s = encode sig
-    len = fromIntegral $ BS.length s
-    rlen = BS.index s 3
-    slen = BS.index s (fromIntegral rlen + 5)
diff --git a/tests/Network/Haskoin/Crypto/ExtendedKeys/Tests.hs b/tests/Network/Haskoin/Crypto/ExtendedKeys/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/ExtendedKeys/Tests.hs
+++ /dev/null
@@ -1,79 +0,0 @@
-module Network.Haskoin.Crypto.ExtendedKeys.Tests (tests) where
-
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.String (fromString)
-import Data.String.Conversions (cs)
-import Data.Word (Word32)
-import Data.Bits ((.&.))
-
-import Network.Haskoin.Test
-import Network.Haskoin.Crypto
-
-tests :: [Test]
-tests =
-    [ testGroup "HDW Extended Keys"
-        [ testProperty "pubkey of subkey is subkey of pubkey / prvSubKey(k,c)*G = pubSubKey(k*G,c)" pubKeyOfSubKeyIsSubKeyOfPubKey
-        , testProperty "fromB58 . toB58 prvKey" b58PrvKey
-        , testProperty "fromB58 . toB58 pubKey" b58PubKey
-        ]
-    , testGroup "From/To strings"
-        [ testProperty "Read/Show extended public key" testReadShowPubKey
-        , testProperty "Read/Show extended private key" testReadShowPrvKey
-        , testProperty "Read/Show derivation path" testReadShowDerivPath
-        , testProperty "Read/Show hard derivation path" testReadShowHardPath
-        , testProperty "Read/Show soft derivation path" testReadShowSoftPath
-        , testProperty "From string extended public key" testFromStringPubKey
-        , testProperty "From string extended private key" testFromStringPrvKey
-        , testProperty "From string derivation path" testFromStringDerivPath
-        , testProperty "From string hard derivation path" testFromStringHardPath
-        , testProperty "From string soft derivation path" testFromStringSoftPath
-        ]
-    ]
-
-{- HDW Extended Keys -}
-
-pubKeyOfSubKeyIsSubKeyOfPubKey :: ArbitraryXPrvKey -> Word32 -> Bool
-pubKeyOfSubKeyIsSubKeyOfPubKey (ArbitraryXPrvKey k) i =
-    (deriveXPubKey $ prvSubKey k i') == (pubSubKey (deriveXPubKey k) i')
-  where
-    i' = fromIntegral $ i .&. 0x7fffffff -- make it a public derivation
-
-b58PrvKey :: ArbitraryXPrvKey -> Bool
-b58PrvKey (ArbitraryXPrvKey k) = (xPrvImport $ xPrvExport k) == Just k
-
-b58PubKey :: ArbitraryXPubKey -> Bool
-b58PubKey (ArbitraryXPubKey _ k) = (xPubImport $ xPubExport k) == Just k
-
-{- Strings -}
-
-testReadShowPubKey :: ArbitraryXPubKey -> Bool
-testReadShowPubKey (ArbitraryXPubKey _ k) = read (show k) == k
-
-testReadShowPrvKey :: ArbitraryXPrvKey -> Bool
-testReadShowPrvKey (ArbitraryXPrvKey k) = read (show k) == k
-
-testFromStringPubKey :: ArbitraryXPubKey -> Bool
-testFromStringPubKey (ArbitraryXPubKey _ k) = fromString (cs $ xPubExport k) == k
-
-testFromStringPrvKey :: ArbitraryXPrvKey -> Bool
-testFromStringPrvKey (ArbitraryXPrvKey k) = fromString (cs $ xPrvExport k) == k
-
-testReadShowDerivPath :: ArbitraryDerivPath -> Bool
-testReadShowDerivPath (ArbitraryDerivPath p) = read (show p) == p
-
-testReadShowHardPath :: ArbitraryHardPath -> Bool
-testReadShowHardPath (ArbitraryHardPath p) = read (show p) == p
-
-testReadShowSoftPath :: ArbitrarySoftPath -> Bool
-testReadShowSoftPath (ArbitrarySoftPath p) = read (show p) == p
-
-testFromStringDerivPath :: ArbitraryDerivPath -> Bool
-testFromStringDerivPath (ArbitraryDerivPath k) = fromString (cs $ pathToStr k) == k
-
-testFromStringHardPath :: ArbitraryHardPath -> Bool
-testFromStringHardPath (ArbitraryHardPath k) = fromString (cs $ pathToStr k) == k
-
-testFromStringSoftPath :: ArbitrarySoftPath -> Bool
-testFromStringSoftPath (ArbitrarySoftPath k) = fromString (cs $ pathToStr k) == k
diff --git a/tests/Network/Haskoin/Crypto/ExtendedKeys/Units.hs b/tests/Network/Haskoin/Crypto/ExtendedKeys/Units.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/ExtendedKeys/Units.hs
+++ /dev/null
@@ -1,429 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Network.Haskoin.Crypto.ExtendedKeys.Units (tests) where
-
-import Test.HUnit (Assertion, assertBool, assertEqual)
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-
-import qualified Data.Aeson as Aeson (decode, encode)
-import Data.Maybe (isJust, isNothing, fromJust)
-import Data.String (fromString)
-import Data.ByteString (ByteString)
-import qualified Data.ByteString.Lazy.Char8 as B8
-import Data.Serialize (encode)
-
-import Network.Haskoin.Crypto
-import Network.Haskoin.Util
-
-tests :: [Test]
-tests =
-    [ testGroup "BIP32 derivation vector 1"
-        [ testCase "Chain m" $ runXKeyVec (xKeyVec !! 0)
-        , testCase "Chain m/0'" $ runXKeyVec (xKeyVec !! 1)
-        , testCase "Chain m/0'/1" $ runXKeyVec (xKeyVec !! 2)
-        , testCase "Chain m/0'/1/2'" $ runXKeyVec (xKeyVec !! 3)
-        , testCase "Chain m/0'/1/2'/2" $ runXKeyVec (xKeyVec !! 4)
-        , testCase "Chain m/0'/1/2'/2/1000000000" $
-            runXKeyVec (xKeyVec !! 5)
-        ]
-    , testGroup "BIP32 subkey derivation vector 2"
-        [ testCase "Chain m" $ runXKeyVec (xKeyVec2 !! 0)
-        , testCase "Chain m/0" $ runXKeyVec (xKeyVec2 !! 1)
-        , testCase "Chain m/0/2147483647'" $
-            runXKeyVec (xKeyVec2 !! 2)
-        , testCase "Chain m/0/2147483647'/1" $
-            runXKeyVec (xKeyVec2 !! 3)
-        , testCase "Chain m/0/2147483647'/1/2147483646'" $
-            runXKeyVec (xKeyVec2 !! 4)
-        , testCase "Chain m/0/2147483647'/1/2147483646'/2" $
-            runXKeyVec (xKeyVec2 !! 5)
-        ]
-    , testGroup "BIP32 subkey derivation using string path"
-        [ testGroup "Either Derivations" testApplyPath
-        , testGroup "Either Derivations" testBadApplyPath
-        , testGroup "Public Derivations" testDerivePubPath
-        , testGroup "Private Derivations" testDerivePrvPath
-        , testGroup "Path Parsing" testParsePath
-        , testGroup "FromJSON" testFromJsonPath
-        , testGroup "ToJSON" testToJsonPath
-        ]
-    ]
-
-testFromJsonPath :: [Test]
-testFromJsonPath = do
-    path <- jsonPathVectors
-    return $ testCase ("Path " ++ path) $
-        assertEqual path (Just [fromString path :: DerivPath])
-            (Aeson.decode $ B8.pack $ "[\"" ++ path ++ "\"]")
-
-testToJsonPath :: [Test]
-testToJsonPath = do
-    path <- jsonPathVectors
-    return $ testCase ("Path " ++ path) $
-        assertEqual path (B8.pack $ "[\"" ++ path ++ "\"]")
-            (Aeson.encode [fromString path :: ParsedPath])
-
-jsonPathVectors :: [String]
-jsonPathVectors =
-    [ "m"
-    , "m/0"
-    , "m/0'"
-    , "M/0'"
-    , "m/2147483647"
-    , "M/2147483647"
-    , "m/1/2/3/4/5/6/7/8"
-    , "M/1/2/3/4/5/6/7/8"
-    , "m/1'/2'/3/4"
-    , "M/1'/2'/3/4"
-    ]
-
-testParsePath :: [Test]
-testParsePath = do
-    (path, t) <- parsePathVectors
-    return $ testCase ("Path " ++ path) $
-        assertBool path (t $ parsePath path)
-
-parsePathVectors :: [(String, Maybe ParsedPath -> Bool)]
-parsePathVectors =
-    [ ("m", isJust)
-    , ("m/0'", isJust)
-    , ("M/0'", isJust)
-    , ("m/2147483648", isNothing)
-    , ("m/2147483647", isJust)
-    , ("M/2147483648", isNothing)
-    , ("M/2147483647", isJust)
-    , ("M/-1", isNothing)
-    , ("M/-2147483648", isNothing)
-    , ("m/1/2/3/4/5/6/7/8", isJust)
-    , ("M/1/2/3/4/5/6/7/8", isJust)
-    , ("m/1'/2'/3/4", isJust)
-    , ("M/1'/2'/3/4", isJust)
-    , ("m/1/2'/3/4'", isJust)
-    , ("M/1/2'/3/4'", isJust)
-    , ("meh", isNothing)
-    , ("infinity", isNothing)
-    , ("NaN", isNothing)
-    ]
-
-testApplyPath :: [Test]
-testApplyPath = do
-    (key, path, final) <- applyPathVectors
-    return $ testCase ("Path " ++ path) $
-        assertEqual path final $
-            applyPath (fromJust $ parsePath path) key
-
-testBadApplyPath :: [Test]
-testBadApplyPath = do
-    (key, path) <- badApplyPathVectors
-    return $ testCase ("Path " ++ path) $
-        assertBool path $ isLeft $
-            applyPath (fromJust $ parsePath path) key
-
-testDerivePubPath :: [Test]
-testDerivePubPath = do
-    (key, path, final) <- derivePubPathVectors
-    return $ testCase ("Path " ++ path) $
-        assertEqual path final $
-            derivePubPath (fromString path :: SoftPath) key
-
-testDerivePrvPath :: [Test]
-testDerivePrvPath = do
-    (key, path, final) <- derivePrvPathVectors
-    return $ testCase ("Path " ++ path) $
-        assertEqual path final $
-            derivePath (fromString path :: DerivPath) key
-
-derivePubPathVectors :: [(XPubKey, String, XPubKey)]
-derivePubPathVectors =
-    [ ( xpub, "M", xpub )
-    , ( xpub, "M/8", pubSubKey xpub 8 )
-    , ( xpub, "M/8/30/1", foldl pubSubKey xpub [8,30,1] )
-    ]
-  where
-    xprv = fromJust $ xPrvImport
-        "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\
-        \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB"
-    xpub = deriveXPubKey xprv
-
-derivePrvPathVectors :: [(XPrvKey, String, XPrvKey)]
-derivePrvPathVectors =
-    [ ( xprv, "m", xprv )
-    , ( xprv, "M", xprv )
-    , ( xprv, "m/8'", hardSubKey xprv 8 )
-    , ( xprv, "M/8'", hardSubKey xprv 8 )
-    , ( xprv, "m/8'/30/1"
-      , foldl prvSubKey (hardSubKey xprv 8) [30,1]
-      )
-    , ( xprv, "M/8'/30/1"
-      , foldl prvSubKey (hardSubKey xprv 8) [30,1]
-      )
-    , ( xprv, "m/3/20"
-      , foldl prvSubKey xprv [3,20]
-      )
-    , ( xprv, "M/3/20"
-      , foldl prvSubKey xprv [3,20]
-      )
-    ]
-  where
-    xprv = fromJust $ xPrvImport
-        "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\
-        \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB"
-
-applyPathVectors :: [(XKey, String, Either String XKey)]
-applyPathVectors =
-    [ ( XPrv xprv, "m", Right $ XPrv xprv )
-    , ( XPrv xprv, "M", Right $ XPub xpub )
-    , ( XPrv xprv, "m/8'", Right $ XPrv $ hardSubKey xprv 8 )
-    , ( XPrv xprv, "M/8'", Right $ XPub $ deriveXPubKey $ hardSubKey xprv 8 )
-    , ( XPrv xprv, "m/8'/30/1"
-      , Right $ XPrv $ foldl prvSubKey (hardSubKey xprv 8) [30,1]
-      )
-    , ( XPrv xprv, "M/8'/30/1"
-      , Right $ XPub $
-          deriveXPubKey $ foldl prvSubKey (hardSubKey xprv 8) [30,1]
-      )
-    , ( XPrv xprv, "m/3/20"
-      , Right $ XPrv $ foldl prvSubKey xprv [3,20]
-      )
-    , ( XPrv xprv, "M/3/20"
-      , Right $ XPub $ deriveXPubKey $ foldl prvSubKey xprv [3,20]
-      )
-    , ( XPub xpub, "M/3/20"
-      , Right $ XPub $ deriveXPubKey $ foldl prvSubKey xprv [3,20]
-      )
-    ]
-  where
-    xprv = fromJust $ xPrvImport
-        "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\
-        \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB"
-    xpub = deriveXPubKey xprv
-
-badApplyPathVectors :: [(XKey, String)]
-badApplyPathVectors = [ 
-    ( XPub xpub, "m/8'" )
-  , ( XPub xpub, "M/8'" )
-  , ( XPub xpub, "M/1/2/3'/4/5" )
-  ]
-  where
-    xprv = fromJust $ xPrvImport
-        "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\
-        \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB"
-    xpub = deriveXPubKey xprv
-
-
-runXKeyVec :: ([ByteString], XPrvKey) -> Assertion
-runXKeyVec (v, m) = do
-    assertBool "xPrvID" $ (encodeHex $ encode $ xPrvID m) == v !! 0
-    assertBool "xPrvFP" $ (encodeHex $ encode $ xPrvFP m) == v !! 1
-    assertBool "xPrvAddr" $
-        (addrToBase58 $ xPubAddr $ deriveXPubKey m) == v !! 2
-    assertBool "prvKey" $
-        (encodeHex $ encodePrvKey $ xPrvKey m) == v !! 3
-    assertBool "xPrvWIF" $ xPrvWif m == v !! 4
-    assertBool "pubKey" $
-        (encodeHex $ encode $ xPubKey $ deriveXPubKey m) == v !! 5
-    assertBool "chain code" $
-        (encodeHex $ encode $ xPrvChain m) == v !! 6
-    assertBool "Hex PubKey" $
-        (encodeHex $ encode $ deriveXPubKey m) == v !! 7
-    assertBool "Hex PrvKey" $ (encodeHex $ encode m) == v !! 8
-    assertBool "Base58 PubKey" $ (xPubExport $ deriveXPubKey m) == v !! 9
-    assertBool "Base58 PrvKey" $ xPrvExport m == v !! 10
-
--- BIP 0032 Test Vectors
--- https://en.bitcoin.it/wiki/BIP_0032_TestVectors
-
-xKeyVec :: [([ByteString], XPrvKey)]
-xKeyVec = zip xKeyResVec $ foldl f [m] der
-    where f acc d = acc ++ [d $ last acc]
-          m   = makeXPrvKey $ fromJust $ decodeHex m0
-          der = [ flip hardSubKey 0
-                , flip prvSubKey 1
-                , flip hardSubKey 2
-                , flip prvSubKey 2
-                , flip prvSubKey 1000000000
-                ]
-
-xKeyVec2 :: [([ByteString], XPrvKey)]
-xKeyVec2 = zip xKeyResVec2 $ foldl f [m] der
-    where f acc d = acc ++ [d $ last acc]
-          m   = makeXPrvKey $ fromJust $ decodeHex m1
-          der = [ flip prvSubKey 0
-                , flip hardSubKey 2147483647
-                , flip prvSubKey 1
-                , flip hardSubKey 2147483646
-                , flip prvSubKey 2
-                ]
-
-m0 :: ByteString
-m0 = "000102030405060708090a0b0c0d0e0f"
-
-xKeyResVec :: [[ByteString]]
-xKeyResVec =
-    [
-      -- m
-      [ "3442193e1bb70916e914552172cd4e2dbc9df811"
-      , "3442193e"
-      , "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma"
-      , "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"
-      , "L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW"
-      , "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"
-      , "873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508"
-      , "0488b21e000000000000000000873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d5080339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2"
-      , "0488ade4000000000000000000873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d50800e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"
-      , "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
-      , "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
-      ]
-      -- m/0'
-    , [ "5c1bd648ed23aa5fd50ba52b2457c11e9e80a6a7"
-      , "5c1bd648"
-      , "19Q2WoS5hSS6T8GjhK8KZLMgmWaq4neXrh"
-      , "edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"
-      , "L5BmPijJjrKbiUfG4zbiFKNqkvuJ8usooJmzuD7Z8dkRoTThYnAT"
-      , "035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"
-      , "47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141"
-      , "0488b21e013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56"
-      , "0488ade4013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae623614100edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea"
-      , "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"
-      , "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7"
-      ]
-      -- m/0'/1
-    , [ "bef5a2f9a56a94aab12459f72ad9cf8cf19c7bbe"
-      , "bef5a2f9"
-      , "1JQheacLPdM5ySCkrZkV66G2ApAXe1mqLj"
-      , "3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"
-      , "KyFAjQ5rgrKvhXvNMtFB5PCSKUYD1yyPEe3xr3T34TZSUHycXtMM"
-      , "03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"
-      , "2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19"
-      , "0488b21e025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c1903501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c"
-      , "0488ade4025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19003c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368"
-      , "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"
-      , "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"
-      ]
-      -- m/0'/1/2'
-    , [ "ee7ab90cde56a8c0e2bb086ac49748b8db9dce72"
-      , "ee7ab90c"
-      , "1NjxqbA9aZWnh17q1UW3rB4EPu79wDXj7x"
-      , "cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"
-      , "L43t3od1Gh7Lj55Bzjj1xDAgJDcL7YFo2nEcNaMGiyRZS1CidBVU"
-      , "0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"
-      , "04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f"
-      , "0488b21e03bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2"
-      , "0488ade403bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f00cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca"
-      , "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"
-      , "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM"
-      ]
-      -- m/0'/1/2'/2
-    , [ "d880d7d893848509a62d8fb74e32148dac68412f"
-      , "d880d7d8"
-      , "1LjmJcdPnDHhNTUgrWyhLGnRDKxQjoxAgt"
-      , "0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"
-      , "KwjQsVuMjbCP2Zmr3VaFaStav7NvevwjvvkqrWd5Qmh1XVnCteBR"
-      , "02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"
-      , "cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd"
-      , "0488b21e04ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29"
-      , "0488ade404ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd000f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4"
-      , "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"
-      , "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334"
-      ]
-      -- m/0'/1/2'/2/1000000000
-    , [ "d69aa102255fed74378278c7812701ea641fdf32"
-      , "d69aa102"
-      , "1LZiqrop2HGR4qrH1ULZPyBpU6AUP49Uam"
-      , "471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"
-      , "Kybw8izYevo5xMh1TK7aUr7jHFCxXS1zv8p3oqFz3o2zFbhRXHYs"
-      , "022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"
-      , "c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e"
-      , "0488b21e05d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011"
-      , "0488ade405d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e00471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8"
-      , "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"
-      , "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76"
-      ]
-    ]
-
-m1 :: ByteString
-m1 = "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"
-
-xKeyResVec2 :: [[ByteString]]
-xKeyResVec2 =
-    [
-      -- m
-      [ "bd16bee53961a47d6ad888e29545434a89bdfe95"
-      , "bd16bee5"
-      , "1JEoxevbLLG8cVqeoGKQiAwoWbNYSUyYjg"
-      , "4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"
-      , "KyjXhyHF9wTphBkfpxjL8hkDXDUSbE3tKANT94kXSyh6vn6nKaoy"
-      , "03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"
-      , "60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689"
-      , "0488b21e00000000000000000060499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd968903cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7"
-      , "0488ade400000000000000000060499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689004b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e"
-      , "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"
-      , "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U"
-      ]
-      -- m/0
-    , [ "5a61ff8eb7aaca3010db97ebda76121610b78096"
-      , "5a61ff8e"
-      , "19EuDJdgfRkwCmRzbzVBHZWQG9QNWhftbZ"
-      , "abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"
-      , "L2ysLrR6KMSAtx7uPqmYpoTeiRzydXBattRXjXz5GDFPrdfPzKbj"
-      , "02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"
-      , "f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c"
-      , "0488b21e01bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea"
-      , "0488ade401bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c00abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e"
-      , "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"
-      , "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt"
-      ]
-      -- m/0/2147483647'
-    , [ "d8ab493736da02f11ed682f88339e720fb0379d1"
-      , "d8ab4937"
-      , "1Lke9bXGhn5VPrBuXgN12uGUphrttUErmk"
-      , "877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"
-      , "L1m5VpbXmMp57P3knskwhoMTLdhAAaXiHvnGLMribbfwzVRpz2Sr"
-      , "03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"
-      , "be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9"
-      , "0488b21e025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d903c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b"
-      , "0488ade4025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d900877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93"
-      , "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"
-      , "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9"
-      ]
-      -- m/0/2147483647'/1
-    , [ "78412e3a2296a40de124307b6485bd19833e2e34"
-      , "78412e3a"
-      , "1BxrAr2pHpeBheusmd6fHDP2tSLAUa3qsW"
-      , "704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"
-      , "KzyzXnznxSv249b4KuNkBwowaN3akiNeEHy5FWoPCJpStZbEKXN2"
-      , "03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"
-      , "f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb"
-      , "0488b21e03d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9"
-      , "0488ade403d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb00704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7"
-      , "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"
-      , "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef"
-      ]
-      -- m/0/2147483647'/1/2147483646'
-    , [ "31a507b815593dfc51ffc7245ae7e5aee304246e"
-      , "31a507b8"
-      , "15XVotxCAV7sRx1PSCkQNsGw3W9jT9A94R"
-      , "f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"
-      , "L5KhaMvPYRW1ZoFmRjUtxxPypQ94m6BcDrPhqArhggdaTbbAFJEF"
-      , "02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"
-      , "637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29"
-      , "0488b21e0478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e2902d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0"
-      , "0488ade40478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e2900f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d"
-      , "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"
-      , "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc"
-      ]
-      -- m/0/2147483647'/1/2147483646'/2
-    , [ "26132fdbe7bf89cbc64cf8dafa3f9f88b8666220"
-      , "26132fdb"
-      , "14UKfRV9ZPUp6ZC9PLhqbRtxdihW9em3xt"
-      , "bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"
-      , "L3WAYNAZPxx1fr7KCz7GN9nD5qMBnNiqEJNJMU1z9MMaannAt4aK"
-      , "024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"
-      , "9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271"
-      , "0488b21e0531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c"
-      , "0488ade40531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed27100bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23"
-      , "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"
-      , "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j"
-      ]
-    ]
-
diff --git a/tests/Network/Haskoin/Crypto/Hash/Tests.hs b/tests/Network/Haskoin/Crypto/Hash/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/Hash/Tests.hs
+++ /dev/null
@@ -1,71 +0,0 @@
-module Network.Haskoin.Crypto.Hash.Tests (tests) where
-
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.String (fromString)
-import Data.String.Conversions (cs)
-import Data.Serialize (encode)
-import Network.Haskoin.Block
-import Network.Haskoin.Crypto
-import Network.Haskoin.Test
-import Network.Haskoin.Util
-
-tests :: [Test]
-tests =
-    [ testGroup "Hash tests"
-        [ testProperty "join512( split512(h) ) == h" joinSplit512
-        , testProperty "decodeCompact . encodeCompact i == i" decEncCompact
-        , testProperty "Read/Show 64-byte hash" testReadShowHash512
-        , testProperty "From string 64-byte hash" testFromStringHash512
-        , testProperty "Read/Show 32-byte hash" testReadShowHash256
-        , testProperty "From string 32-byte hash" testFromStringHash256
-        , testProperty "Read/Show 20-byte hash" testReadShowHash160
-        , testProperty "From string 20-byte hash" testFromStringHash160
-        , testProperty "Read/Show checksum" testReadShowCheckSum32
-        , testProperty "From string checksum" testFromStringCheckSum32
-        ]
-    ]
-
-joinSplit512 :: (ArbitraryHash256, ArbitraryHash256) -> Bool
-joinSplit512 (ArbitraryHash256 a, ArbitraryHash256 b) =
-    (split512 $ join512 (a, b)) == (a, b)
-
--- After encoding and decoding, we may loose precision so the new result is >=
--- to the old one.
-decEncCompact :: Integer -> Bool
-decEncCompact i
-    -- Integer completely fits inside the mantisse
-    | (abs i) <= 0x007fffff = (decodeCompact $ encodeCompact i) == i
-    -- Otherwise precision will be lost and the decoded result will
-    -- be smaller than the original number
-    | i >= 0                = (decodeCompact $ encodeCompact i) < i
-    | otherwise             = (decodeCompact $ encodeCompact i) > i
-
-
-testReadShowHash512 :: ArbitraryHash512 -> Bool
-testReadShowHash512 (ArbitraryHash512 k) = read (show k) == k
-
-testFromStringHash512 :: ArbitraryHash512 -> Bool
-testFromStringHash512 (ArbitraryHash512 k) = fromString (cs $ encodeHex $ encode k) == k
-
-
-testReadShowHash256 :: ArbitraryHash256 -> Bool
-testReadShowHash256 (ArbitraryHash256 k) = read (show k) == k
-
-testFromStringHash256 :: ArbitraryHash256 -> Bool
-testFromStringHash256 (ArbitraryHash256 k) = fromString (cs $ encodeHex $ encode k) == k
-
-
-testReadShowHash160 :: ArbitraryHash160 -> Bool
-testReadShowHash160 (ArbitraryHash160 k) = read (show k) == k
-
-testFromStringHash160 :: ArbitraryHash160 -> Bool
-testFromStringHash160 (ArbitraryHash160 k) = fromString (cs $ encodeHex $ encode k) == k
-
-
-testReadShowCheckSum32 :: ArbitraryCheckSum32 -> Bool
-testReadShowCheckSum32 (ArbitraryCheckSum32 k) = read (show k) == k
-
-testFromStringCheckSum32 :: ArbitraryCheckSum32 -> Bool
-testFromStringCheckSum32 (ArbitraryCheckSum32 k) = fromString (cs $ encodeHex $ encode k) == k
diff --git a/tests/Network/Haskoin/Crypto/Hash/Units.hs b/tests/Network/Haskoin/Crypto/Hash/Units.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/Hash/Units.hs
+++ /dev/null
@@ -1,1270 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Network.Haskoin.Crypto.Hash.Units (tests) where
-
-import Test.HUnit (assertBool, Assertion)
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-
-import Data.Maybe (fromJust)
-import Data.ByteString (ByteString)
-
-import Network.Haskoin.Block
-import Network.Haskoin.Util
-import Network.Haskoin.Internals (hmacDRBGNew, hmacDRBGGen, hmacDRBGRsd)
-
--- Test vectors from NIST
--- http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
--- About 1/3 of HMAC DRBG SHA-256 test vectors are tested here
-
-tests :: [Test]
-tests =
-    [ testGroup "HMAC DRBG Suite 1" [mapDRBG t1]
-    , testGroup "HMAC DRBG Suite 2" [mapDRBG t2]
-    , testGroup "HMAC DRBG Suite 3" [mapDRBG t3]
-    , testGroup "HMAC DRBG Suite 4" [mapDRBG t4]
-    , testGroup "HMAC DRBG Suite 5 (Reseed)" [mapDRBGRsd r1]
-    , testGroup "HMAC DRBG Suite 6 (Reseed)" [mapDRBGRsd r2]
-    , testGroup "HMAC DRBG Suite 7 (Reseed)" [mapDRBGRsd r3]
-    , testGroup "HMAC DRBG Suite 8 (Reseed)" [mapDRBGRsd r4]
-    , testGroup "Compact number representation"
-        [ testCase "Compact number representations" testCompact ]
-    ]
-
-type TestVector = [ByteString]
-
-mapDRBG :: [TestVector] -> Test.Framework.Test
-mapDRBG vs = testCase "HMAC DRBG Vectors" $ mapM_ testDRBG $ zip vs [0..]
-
-mapDRBGRsd :: [TestVector] -> Test.Framework.Test
-mapDRBGRsd vs = testCase "HMAC DRBG Vectors" $ mapM_ testDRBGRsd $ zip vs [0..]
-
-testDRBG :: (TestVector, Int) -> Assertion
-testDRBG (s,i) = do
-    let w1     = hmacDRBGNew (v !! 0) (v !! 1) (v !! 2)
-        (w2,_) = hmacDRBGGen w1 128 (v !! 3)
-        (_,r)  = hmacDRBGGen w2 128 (v !! 4)
-    assertBool name $ fromJust r == (v !! 5)
-    where v = map (fromJust . decodeHex) s
-          name = "    > HMAC DRBG Vector " ++ (show i)
-
-testDRBGRsd :: (TestVector, Int) -> Assertion
-testDRBGRsd (s,i) = do
-    let w1 = hmacDRBGNew (v !! 0) (v !! 1) (v !! 2)
-        w2 = hmacDRBGRsd w1 (v !! 3) (v !! 4)
-        (w3,_) = hmacDRBGGen w2 128 (v !! 5)
-        (_,r)  = hmacDRBGGen w3 128 (v !! 6)
-    assertBool name $ fromJust r == (v !! 7)
-    where v = map (fromJust . decodeHex) s
-          name = "    > HMAC DRBG Vector " ++ (show i)
-
-testCompact :: Assertion
-testCompact = do
-    assertBool "Vector 1" $ (encodeCompact 0x1234560000)    == 0x05123456
-    assertBool "Vector 2" $ (decodeCompact 0x05123456)      == 0x1234560000
-    assertBool "Vector 3" $ (encodeCompact 0xc0de000000)    == 0x0600c0de
-    assertBool "Vector 4" $ (decodeCompact 0x0600c0de)      == 0xc0de000000
-    assertBool "Vector 5" $ (encodeCompact (-0x40de000000)) == 0x05c0de00
-    assertBool "Vector 6" $ (decodeCompact 0x05c0de00)      == (-0x40de000000)
-
-{-
-    [SHA-256]
-    [PredictionResistance = False]
-    [EntropyInputLen = 256]
-    [NonceLen = 128]
-    [PersonalizationStringLen = 0]
-    [AdditionalInputLen = 0]
-    [ReturnedBitsLen = 1024]
--}
-
-t1 :: [TestVector]
-t1 =
-    [
-    -- COUNT = 0
-    [ "ca851911349384bffe89de1cbdc46e6831e44d34a4fb935ee285dd14b71a7488"
-    , "659ba96c601dc69fc902940805ec0ca8"
-    , ""
-    , ""
-    , ""
-    , "e528e9abf2dece54d47c7e75e5fe302149f817ea9fb4bee6f4199697d04d5b89d54fbb978a15b5c443c9ec21036d2460b6f73ebad0dc2aba6e624abf07745bc107694bb7547bb0995f70de25d6b29e2d3011bb19d27676c07162c8b5ccde0668961df86803482cb37ed6d5c0bb8d50cf1f50d476aa0458bdaba806f48be9dcb8"
-    ],
-    -- COUNT = 1
-    [ "79737479ba4e7642a221fcfd1b820b134e9e3540a35bb48ffae29c20f5418ea3"
-    , "3593259c092bef4129bc2c6c9e19f343"
-    , ""
-    , ""
-    , ""
-    , "cf5ad5984f9e43917aa9087380dac46e410ddc8a7731859c84e9d0f31bd43655b924159413e2293b17610f211e09f770f172b8fb693a35b85d3b9e5e63b1dc252ac0e115002e9bedfb4b5b6fd43f33b8e0eafb2d072e1a6fee1f159df9b51e6c8da737e60d5032dd30544ec51558c6f080bdbdab1de8a939e961e06b5f1aca37"
-    ],
-    -- COUNT = 2
-    [ "b340907445b97a8b589264de4a17c0bea11bb53ad72f9f33297f05d2879d898d"
-    , "65cb27735d83c0708f72684ea58f7ee5"
-    , ""
-    , ""
-    , ""
-    , "75183aaaf3574bc68003352ad655d0e9ce9dd17552723b47fab0e84ef903694a32987eeddbdc48efd24195dbdac8a46ba2d972f5808f23a869e71343140361f58b243e62722088fe10a98e43372d252b144e00c89c215a76a121734bdc485486f65c0b16b8963524a3a70e6f38f169c12f6cbdd169dd48fe4421a235847a23ff"
-    ],
-    -- COUNT = 3
-    [ "8e159f60060a7d6a7e6fe7c9f769c30b98acb1240b25e7ee33f1da834c0858e7"
-    , "c39d35052201bdcce4e127a04f04d644"
-    , ""
-    , ""
-    , ""
-    , "62910a77213967ea93d6457e255af51fc79d49629af2fccd81840cdfbb4910991f50a477cbd29edd8a47c4fec9d141f50dfde7c4d8fcab473eff3cc2ee9e7cc90871f180777a97841597b0dd7e779eff9784b9cc33689fd7d48c0dcd341515ac8fecf5c55a6327aea8d58f97220b7462373e84e3b7417a57e80ce946d6120db5"
-    ],
-    -- COUNT = 4
-    [ "74755f196305f7fb6689b2fe6835dc1d81484fc481a6b8087f649a1952f4df6a"
-    , "c36387a544a5f2b78007651a7b74b749"
-    , ""
-    , ""
-    , ""
-    , "b2896f3af4375dab67e8062d82c1a005ef4ed119d13a9f18371b1b873774418684805fd659bfd69964f83a5cfe08667ddad672cafd16befffa9faed49865214f703951b443e6dca22edb636f3308380144b9333de4bcb0735710e4d9266786342fc53babe7bdbe3c01a3addb7f23c63ce2834729fabbd419b47beceb4a460236"
-    ],
-    -- COUNT = 5
-    [ "4b222718f56a3260b3c2625a4cf80950b7d6c1250f170bd5c28b118abdf23b2f"
-    , "7aed52d0016fcaef0b6492bc40bbe0e9"
-    , ""
-    , ""
-    , ""
-    , "a6da029b3665cd39fd50a54c553f99fed3626f4902ffe322dc51f0670dfe8742ed48415cf04bbad5ed3b23b18b7892d170a7dcf3ef8052d5717cb0c1a8b3010d9a9ea5de70ae5356249c0e098946030c46d9d3d209864539444374d8fbcae068e1d6548fa59e6562e6b2d1acbda8da0318c23752ebc9be0c1c1c5b3cf66dd967"
-    ],
-    -- COUNT = 6
-    [ "b512633f27fb182a076917e39888ba3ff35d23c3742eb8f3c635a044163768e0"
-    , "e2c39b84629a3de5c301db5643af1c21"
-    , ""
-    , ""
-    , ""
-    , "fb931d0d0194a97b48d5d4c231fdad5c61aedf1c3a55ac24983ecbf38487b1c93396c6b86ff3920cfa8c77e0146de835ea5809676e702dee6a78100da9aa43d8ec0bf5720befa71f82193205ac2ea403e8d7e0e6270b366dc4200be26afd9f63b7e79286a35c688c57cbff55ac747d4c28bb80a2b2097b3b62ea439950d75dff"
-    ],
-    -- COUNT = 7
-    [ "aae3ffc8605a975befefcea0a7a286642bc3b95fb37bd0eb0585a4cabf8b3d1e"
-    , "9504c3c0c4310c1c0746a036c91d9034"
-    , ""
-    , ""
-    , ""
-    , "2819bd3b0d216dad59ddd6c354c4518153a2b04374b07c49e64a8e4d055575dfbc9a8fcde68bd257ff1ba5c6000564b46d6dd7ecd9c5d684fd757df62d85211575d3562d7814008ab5c8bc00e7b5a649eae2318665b55d762de36eba00c2906c0e0ec8706edb493e51ca5eb4b9f015dc932f262f52a86b11c41e9a6d5b3bd431"
-    ],
-    -- COUNT = 8
-    [ "b9475210b79b87180e746df704b3cbc7bf8424750e416a7fbb5ce3ef25a82cc6"
-    , "24baf03599c10df6ef44065d715a93f7"
-    , ""
-    , ""
-    , ""
-    , "ae12d784f796183c50db5a1a283aa35ed9a2b685dacea97c596ff8c294906d1b1305ba1f80254eb062b874a8dfffa3378c809ab2869aa51a4e6a489692284a25038908a347342175c38401193b8afc498077e10522bec5c70882b7f760ea5946870bd9fc72961eedbe8bff4fd58c7cc1589bb4f369ed0d3bf26c5bbc62e0b2b2"
-    ],
-    -- COUNT = 9
-    [ "27838eb44ceccb4e36210703ebf38f659bc39dd3277cd76b7a9bcd6bc964b628"
-    , "39cfe0210db2e7b0eb52a387476e7ea1"
-    , ""
-    , ""
-    , ""
-    , "e5e72a53605d2aaa67832f97536445ab774dd9bff7f13a0d11fd27bf6593bfb52309f2d4f09d147192199ea584503181de87002f4ee085c7dc18bf32ce5315647a3708e6f404d6588c92b2dda599c131aa350d18c747b33dc8eda15cf40e95263d1231e1b4b68f8d829f86054d49cfdb1b8d96ab0465110569c8583a424a099a"
-    ],
-    -- COUNT = 10
-    [ "d7129e4f47008ad60c9b5d081ff4ca8eb821a6e4deb91608bf4e2647835373a5"
-    , "a72882773f78c2fc4878295840a53012"
-    , ""
-    , ""
-    , ""
-    , "0cbf48585c5de9183b7ff76557f8fc9ebcfdfde07e588a8641156f61b7952725bbee954f87e9b937513b16bba0f2e523d095114658e00f0f3772175acfcb3240a01de631c19c5a834c94cc58d04a6837f0d2782fa53d2f9f65178ee9c837222494c799e64c60406069bd319549b889fa00a0032dd7ba5b1cc9edbf58de82bfcd"
-    ],
-    -- COUNT = 11
-    [ "67fe5e300c513371976c80de4b20d4473889c9f1214bce718bc32d1da3ab7532"
-    , "e256d88497738a33923aa003a8d7845c"
-    , ""
-    , ""
-    , ""
-    , "b44660d64ef7bcebc7a1ab71f8407a02285c7592d755ae6766059e894f694373ed9c776c0cfc8594413eefb400ed427e158d687e28da3ecc205e0f7370fb089676bbb0fa591ec8d916c3d5f18a3eb4a417120705f3e2198154cd60648dbfcfc901242e15711cacd501b2c2826abe870ba32da785ed6f1fdc68f203d1ab43a64f"
-    ],
-    -- COUNT = 12
-    [ "de8142541255c46d66efc6173b0fe3ffaf5936c897a3ce2e9d5835616aafa2cb"
-    , "d01f9002c407127bc3297a561d89b81d"
-    , ""
-    , ""
-    , ""
-    , "64d1020929d74716446d8a4e17205d0756b5264867811aa24d0d0da8644db25d5cde474143c57d12482f6bf0f31d10af9d1da4eb6d701bdd605a8db74fb4e77f79aaa9e450afda50b18d19fae68f03db1d7b5f1738d2fdce9ad3ee9461b58ee242daf7a1d72c45c9213eca34e14810a9fca5208d5c56d8066bab1586f1513de7"
-    ],
-    -- COUNT = 13
-    [ "4a8e0bd90bdb12f7748ad5f147b115d7385bb1b06aee7d8b76136a25d779bcb7"
-    , "7f3cce4af8c8ce3c45bdf23c6b181a00"
-    , ""
-    , ""
-    , ""
-    , "320c7ca4bbeb7af977bc054f604b5086a3f237aa5501658112f3e7a33d2231f5536d2c85c1dad9d9b0bf7f619c81be4854661626839c8c10ae7fdc0c0b571be34b58d66da553676167b00e7d8e49f416aacb2926c6eb2c66ec98bffae20864cf92496db15e3b09e530b7b9648be8d3916b3c20a3a779bec7d66da63396849aaf"
-    ],
-    -- COUNT = 14
-    [ "451ed024bc4b95f1025b14ec3616f5e42e80824541dc795a2f07500f92adc665"
-    , "2f28e6ee8de5879db1eccd58c994e5f0"
-    , ""
-    , ""
-    , ""
-    , "3fb637085ab75f4e95655faae95885166a5fbb423bb03dbf0543be063bcd48799c4f05d4e522634d9275fe02e1edd920e26d9accd43709cb0d8f6e50aa54a5f3bdd618be23cf73ef736ed0ef7524b0d14d5bef8c8aec1cf1ed3e1c38a808b35e61a44078127c7cb3a8fd7addfa50fcf3ff3bc6d6bc355d5436fe9b71eb44f7fd"
-    ]
-    ]
-
-{-
-    [SHA-256]
-    [PredictionResistance = False]
-    [EntropyInputLen = 256]
-    [NonceLen = 128]
-    [PersonalizationStringLen = 0]
-    [AdditionalInputLen = 256]
-    [ReturnedBitsLen = 1024]
--}
-
-t2 :: [TestVector]
-t2 =
-    [
-    -- COUNT = 0
-    [ "d3cc4d1acf3dde0c4bd2290d262337042dc632948223d3a2eaab87da44295fbd"
-    , "0109b0e729f457328aa18569a9224921"
-    , ""
-    , "3c311848183c9a212a26f27f8c6647e40375e466a0857cc39c4e47575d53f1f6"
-    , "fcb9abd19ccfbccef88c9c39bfb3dd7b1c12266c9808992e305bc3cff566e4e4"
-    , "9c7b758b212cd0fcecd5daa489821712e3cdea4467b560ef5ddc24ab47749a1f1ffdbbb118f4e62fcfca3371b8fbfc5b0646b83e06bfbbab5fac30ea09ea2bc76f1ea568c9be0444b2cc90517b20ca825f2d0eccd88e7175538b85d90ab390183ca6395535d34473af6b5a5b88f5a59ee7561573337ea819da0dcc3573a22974"
-    ],
-    -- COUNT = 1
-    [ "f97a3cfd91faa046b9e61b9493d436c4931f604b22f1081521b3419151e8ff06"
-    , "11f3a7d43595357d58120bd1e2dd8aed"
-    , ""
-    , "517289afe444a0fe5ed1a41dbbb5eb17150079bdd31e29cf2ff30034d8268e3b"
-    , "88028d29ef80b4e6f0fe12f91d7449fe75062682e89c571440c0c9b52c42a6e0"
-    , "c6871cff0824fe55ea7689a52229886730450e5d362da5bf590dcf9acd67fed4cb32107df5d03969a66b1f6494fdf5d63d5b4d0d34ea7399a07d0116126d0d518c7c55ba46e12f62efc8fe28a51c9d428e6d371d7397ab319fc73ded4722e5b4f30004032a6128df5e7497ecf82ca7b0a50e867ef6728a4f509a8c859087039c"
-    ],
-    -- COUNT = 2
-    [ "0f2f23d64f481cabec7abb01db3aabf125c3173a044b9bf26844300b69dcac8b"
-    , "9a5ae13232b43aa19cfe8d7958b4b590"
-    , ""
-    , "ec4c7a62acab73385f567da10e892ff395a0929f959231a5628188ce0c26e818"
-    , "6b97b8c6b6bb8935e676c410c17caa8042aa3145f856d0a32b641e4ae5298648"
-    , "7480a361058bd9afa3db82c9d7586e42269102013f6ec5c269b6d05f17987847748684766b44918fd4b65e1648622fc0e0954178b0279dfc9fa99b66c6f53e51c4860131e9e0644287a4afe4ca8e480417e070db68008a97c3397e4b320b5d1a1d7e1d18a95cfedd7d1e74997052bf649d132deb9ec53aae7dafdab55e6dae93"
-    ],
-    -- COUNT = 3
-    [ "53c56660c78481be9c63284e005fcc14fbc7fb27732c9bf1366d01a426765a31"
-    , "dc7a14d0eb5b0b3534e717a0b3c64614"
-    , ""
-    , "3aa848706ecb877f5bedf4ffc332d57c22e08747a47e75cff6f0fd1316861c95"
-    , "9a401afa739b8f752fddacd291e0b854f5eff4a55b515e20cb319852189d3722"
-    , "5c0eb420e0bf41ce9323e815310e4e8303cd677a8a8b023f31f0d79f0ca15aeb636099a369fd074d69889865eac1b72ab3cbfebdb8cf460b00072802e2ec648b1349a5303be4ccaadd729f1a9ea17482fd026aaeb93f1602bc1404b9853adde40d6c34b844cf148bc088941ecfc1642c8c0b9778e45f3b07e06e21ee2c9e0300"
-    ],
-    -- COUNT = 4
-    [ "f63c804404902db334c54bb298fc271a21d7acd9f770278e089775710bf4fdd7"
-    , "3e45009ea9cb2a36ba1aa4bf39178200"
-    , ""
-    , "d165a13dc8cc43f3f0952c3f5d3de4136954d983683d4a3e6d2dc4c89bf23423"
-    , "75106bc86d0336df85097f6af8e80e2da59046a03fa65b06706b8bbc7ffc6785"
-    , "6363139bba32c22a0f5cd23ca6d437b5669b7d432f786b8af445471bee0b2d24c9d5f2f93717cbe00d1f010cc3b9c515fc9f7336d53d4d26ba5c0d76a90186663c8582eb739c7b6578a3328bf68dc2cec2cd89b3a90201f6993adcc854df0f5c6974d0f5570765a15fe03dbce28942dd2fd16ba2027e68abac83926969349af8"
-    ],
-    -- COUNT = 5
-    [ "2aaca9147da66c176615726b69e3e851cc3537f5f279fe7344233d8e44cfc99d"
-    , "4e171f080af9a6081bee9f183ac9e340"
-    , ""
-    , "d75a2a6eb66c3833e50f5ec3d2e434cf791448d618026d0c360806d120ded669"
-    , "b643b74c15b37612e6577ed7ca2a4c67a78d560af9eb50a4108fca742e87b8d6"
-    , "501dcdc977f4ba856f24eaa4968b374bebb3166b280334cb510232c31ebffde10fa47b7840ef3fe3b77725c2272d3a1d4219baf23e0290c622271edcced58838cf428f0517425d2e19e0d8c89377eecfc378245f283236fafa466c914b99672ceafab369e8889a0c866d8bd639db9fb797254262c6fd44cfa9045ad6340a60ef"
-    ],
-    -- COUNT = 6
-    [ "a2e4cd48a5cf918d6f55942d95fcb4e8465cdc4f77b7c52b6fae5b16a25ca306"
-    , "bef036716440db6e6d333d9d760b7ca8"
-    , ""
-    , "bfa591c7287f3f931168f95e38869441d1f9a11035ad8ea625bb61b9ea17591c"
-    , "c00c735463bca215adc372cb892b05e939bf669583341c06d4e31d0e5b363a37"
-    , "e7d136af69926a5421d4266ee0420fd729f2a4f7c295d3c966bdfa05268180b508b8a2852d1b3a06fd2ab3e13c54005123ef319f42d0c6d3a575e6e7e1496cb28aacadbcf83740fba8f35fcee04bb2ed8a51db3d3362b01094a62fb57e33c99a432f29fce6676cffbbcc05107e794e75e44a02d5e6d9d748c5fbff00a0178d65"
-    ],
-    -- COUNT = 7
-    [ "95a67771cba69011a79776e713145d309edae56fad5fd6d41d83eaff89df6e5e"
-    , "be5b5164e31ecc51ba6f7c3c5199eb33"
-    , ""
-    , "065f693b229a7c4fd373cd15b3807552dd9bf98c5485cef361949d4e7d774b53"
-    , "9afb62406f0e812c4f156d58b19a656c904813c1b4a45a0029ae7f50731f8014"
-    , "f61b61a6e79a41183e8ed6647899d2dc85cdaf5c3abf5c7f3bf37685946dc28f4923dc842f2d4326bd6ce0d50a84cb3ba869d72a36e246910eba6512ba36cd7ed3a5437c9245b00a344308c792b668b458d3c3e16dee2fbec41867da31084d46d8ec168de2148ef64fc5b72069abf5a6ada1ead2b7146bb793ff1c9c3690fa56"
-    ],
-    -- COUNT = 8
-    [ "a459e1815cbca4514ec8094d5ab2414a557ba6fe10e613c345338d0521e4bf90"
-    , "62221392e2552e76cd0d36df6e6068eb"
-    , ""
-    , "0a3642b02b23b3ef62c701a63401124022f5b896de86dab6e6c7451497aa1dcc"
-    , "c80514865901371c45ba92d9f95d50bb7c9dd1768cb3dfbc45b968da94965c6e"
-    , "464e6977b8adaef307c9623e41c357013249c9ffd77f405f3925cebb69f151ce8fbb6a277164002aee7858fc224f6499042aa1e6322deee9a5d133c31d640e12a7487c731ba03ad866a24675badb1d79220c40be689f79c2a0be93cb4dada3e0eac4ab140cb91998b6f11953e68f2319b050c40f71c34de9905ae41b2de1c2f6"
-    ],
-    -- COUNT = 9
-    [ "252c2cad613e002478162861880979ee4e323025eebb6fb2e0aa9f200e28e0a1"
-    , "d001bc9a8f2c8c242e4369df0c191989"
-    , ""
-    , "9bcfc61cb2bc000034bb3db980eb47c76fb5ecdd40553eff113368d639b947fd"
-    , "8b0565c767c2610ee0014582e9fbecb96e173005b60e9581503a6dca5637a26e"
-    , "e96c15fe8a60692b0a7d67171e0195ff6e1c87aab844221e71700d1bbee75feea695f6a740c9760bbe0e812ecf4061d8f0955bc0195e18c4fd1516ebca50ba6a6db86881737dbab8321707675479b87611db6af2c97ea361a5484555ead454defb1a64335de964fc803d40f3a6f057893d2afc25725754f4f00abc51920743dc"
-    ],
-    -- COUNT = 10
-    [ "8be0ca6adc8b3870c9d69d6021bc1f1d8eb9e649073d35ee6c5aa0b7e56ad8a5"
-    , "9d1265f7d51fdb65377f1e6edd6ae0e4"
-    , ""
-    , "da86167ac997c406bb7979f423986a84ec6614d6caa7afc10aff0699a9b2cf7f"
-    , "e4baa3c555950b53e2bfdba480cb4c94b59381bac1e33947e0c22e838a9534cf"
-    , "64384ecc4ea6b458efc227ca697eac5510092265520c0a0d8a0ccf9ed3ca9d58074671188c6a7ad16d0b050cdc072c125d7298d3a31d9f044a9ee40da0089a84fea28cc7f05f1716db952fad29a0e779635cb7a912a959be67be2f0a4170aace2981802e2ff6467e5b46f0ffbff3b42ba5935fd553c82482ac266acf1cd247d7"
-    ],
-    -- COUNT = 11
-    [ "d43a75b6adf26d60322284cb12ac38327792442aa8f040f60a2f331b33ac4a8f"
-    , "0682f8b091f811afacaacaec9b04d279"
-    , ""
-    , "7fd3b8f512940da7de5d80199d9a7b42670c04a945775a3dba869546cbb9bc65"
-    , "2575db20bc7aafc2a90a5dabab760db851d754777bc9f05616af1858b24ff3da"
-    , "0da7a8dc73c163014bf0841913d3067806456bbca6d5de92b85534c6545467313648d71ef17c923d090dc92cff8d4d1a9a2bb63e001dc2e8ab1a597999be3d6cf70ff63fee9985801395fbd4f4990430c4259fcae4fa1fcd73dc3187ccc102d04af7c07532885e5a226fc42809c48f22eecf4f6ab996ae4fcb144786957d9f41"
-    ],
-    -- COUNT = 12
-    [ "64352f236af5d32067a529a8fd05ba00a338c9de306371a0b00c36e610a48d18"
-    , "df99ed2c7608c870624b962a5dc68acd"
-    , ""
-    , "da416335e7aaf60cf3d06fb438735ce796aad09034f8969c8f8c3f81e32fef24"
-    , "a28c07c21a2297311adf172c19e83ca0a87731bdffb80548978d2d1cd82cf8a3"
-    , "132b9f25868729e3853d3c51f99a3b5fae6d4204bea70890daf62e042b776a526c8fb831b80a6d5d3f153237df1fd39b6fd9137963f5516d9cdd4e3f9195c46e9972c15d3edc6606e3368bde1594977fb88d0ca6e6f5f3d057ccadc7d7dab77dfc42658a1e972aa446b20d418286386a52dfc1c714d2ac548713268b0b709729"
-    ],
-    -- COUNT = 13
-    [ "282f4d2e05a2cd30e9087f5633089389449f04bac11df718c90bb351cd3653a5"
-    , "90a7daf3c0de9ea286081efc4a684dfb"
-    , ""
-    , "2630b4ccc7271cc379cb580b0aaede3d3aa8c1c7ba002cf791f0752c3d739007"
-    , "c31d69de499f1017be44e3d4fa77ecebc6a9b9934749fcf136f267b29115d2cc"
-    , "c899094520e0197c37b91dd50778e20a5b950decfb308d39f1db709447ae48f6101d9abe63a783fbb830eec1d359a5f61a2013728966d349213ee96382614aa4135058a967627183810c6622a2158cababe3b8ab99169c89e362108bf5955b4ffc47440f87e4bad0d36bc738e737e072e64d8842e7619f1be0af1141f05afe2d"
-    ],
-    -- COUNT = 14
-    [ "13c752b9e745ce77bbc7c0dbda982313d3fe66f903e83ebd8dbe4ff0c11380e9"
-    , "f1a533095d6174164bd7c82532464ae7"
-    , ""
-    , "4f53db89b9ba7fc00767bc751fb8f3c103fe0f76acd6d5c7891ab15b2b7cf67c"
-    , "582c2a7d34679088cca6bd28723c99aac07db46c332dc0153d1673256903b446"
-    , "6311f4c0c4cd1f86bd48349abb9eb930d4f63df5e5f7217d1d1b91a71d8a6938b0ad2b3e897bd7e3d8703db125fab30e03464fad41e5ddf5bf9aeeb5161b244468cfb26a9d956931a5412c97d64188b0da1bd907819c686f39af82e91cfeef0cbffb5d1e229e383bed26d06412988640706815a6e820796876f416653e464961"
-    ]
-    ]
-
-{-
-    [SHA-256]
-    [PredictionResistance = False]
-    [EntropyInputLen = 256]
-    [NonceLen = 128]
-    [PersonalizationStringLen = 256]
-    [AdditionalInputLen = 0]
-    [ReturnedBitsLen = 1024]
--}
-
-t3 :: [TestVector]
-t3 =
-    [
-    -- COUNT = 0
-    [ "5cacc68165a2e2ee20812f35ec73a79dbf30fd475476ac0c44fc6174cdac2b55"
-    , "6f885496c1e63af620becd9e71ecb824"
-    , "e72dd8590d4ed5295515c35ed6199e9d211b8f069b3058caa6670b96ef1208d0"
-    , ""
-    , ""
-    , "f1012cf543f94533df27fedfbf58e5b79a3dc517a9c402bdbfc9a0c0f721f9d53faf4aafdc4b8f7a1b580fcaa52338d4bd95f58966a243cdcd3f446ed4bc546d9f607b190dd69954450d16cd0e2d6437067d8b44d19a6af7a7cfa8794e5fbd728e8fb2f2e8db5dd4ff1aa275f35886098e80ff844886060da8b1e7137846b23b"
-    ],
-    -- COUNT = 1
-    [ "8df013b4d103523073917ddf6a869793059e9943fc8654549e7ab22f7c29f122"
-    , "da2625af2ddd4abcce3cf4fa4659d84e"
-    , "b571e66d7c338bc07b76ad3757bb2f9452bf7e07437ae8581ce7bc7c3ac651a9"
-    , ""
-    , ""
-    , "b91cba4cc84fa25df8610b81b641402768a2097234932e37d590b1154cbd23f97452e310e291c45146147f0da2d81761fe90fba64f94419c0f662b28c1ed94da487bb7e73eec798fbcf981b791d1be4f177a8907aa3c401643a5b62b87b89d66b3a60e40d4a8e4e9d82af6d2700e6f535cdb51f75c321729103741030ccc3a56"
-    ],
-    -- COUNT = 2
-    [ "565b2b77937ba46536b0f693b3d5e4a8a24563f9ef1f676e8b5b2ef17823832f"
-    , "4ef3064ec29f5b7f9686d75a23d170e3"
-    , "3b722433226c9dba745087270ab3af2c909425ba6d39f5ce46f07256068319d9"
-    , ""
-    , ""
-    , "d144ee7f8363d128872f82c15663fe658413cd42651098e0a7c51a970de75287ec943f9061e902280a5a9e183a7817a44222d198fbfab184881431b4adf35d3d1019da5a90b3696b2349c8fba15a56d0f9d010a88e3f9eeedb67a69bcaa71281b41afa11af576b765e66858f0eb2e4ec4081609ec81da81df0a0eb06787340ea"
-    ],
-    -- COUNT = 3
-    [ "fc3832a91b1dcdcaa944f2d93cbceb85c267c491b7b59d017cde4add79a836b6"
-    , "d5e76ce9eabafed06e33a913e395c5e0"
-    , "ffc5f6eefd51da64a0f67b5f0cf60d7ab43fc7836bca650022a0cee57a43c148"
-    , ""
-    , ""
-    , "0e713c6cc9a4dbd4249201d12b7bf5c69c3e18eb504bf3252db2f43675e17d99b6a908400cea304011c2e54166dae1f20260008efe4e06a87e0ce525ca482bca223a902a14adcf2374a739a5dfeaf14cadd72efa4d55d15154c974d9521535bcb70658c5b6c944020afb04a87b223b4b8e5d89821704a9985bb010405ba8f3d4"
-    ],
-    -- COUNT = 4
-    [ "8009eb2cb49fdf16403bcdfd4a9f952191062acb9cc111eca019f957fb9f4451"
-    , "355598866952394b1eddd85d59f81c9d"
-    , "09ff1d4b97d83b223d002e05f754be480d13ba968e5aac306d71cc9fc49cc2dd"
-    , ""
-    , ""
-    , "9550903c2f02cf77c8f9c9a37041d0040ee1e3ef65ba1a1fbbcf44fb7a2172bd6b3aaabe850281c3a1778277bacd09614dfefececac64338ae24a1bf150cbf9d9541173a82ecba08aa19b75abb779eb10efa4257d5252e8afcac414bc3bb5d3006b6f36fb9daea4c8c359ef6cdbeff27c1068571dd3c89dc87eda9190086888d"
-    ],
-    -- COUNT = 5
-    [ "a6e4c9a8bd6da23b9c2b10a7748fd08c4f782fadbac7ea501c17efdc6f6087bd"
-    , "acdc47edf1d3b21d0aec7631abb6d7d5"
-    , "c16ee0908a5886dccf332fbc61de9ec7b7972d2c4c83c477409ce8a15c623294"
-    , ""
-    , ""
-    , "a52f93ccb363e2bdf0903622c3caedb7cffd04b726052b8d455744c71b76dee1b71db9880dc3c21850489cb29e412d7d80849cfa9151a151dcbf32a32b4a54cac01d3200200ed66a3a5e5c131a49655ffbf1a8824ff7f265690dffb4054df46a707b9213924c631c5bce379944c856c4f7846e281ac89c64fad3a49909dfb92b"
-    ],
-    -- COUNT = 6
-    [ "59d6307460a9bdd392dfc0904973991d585696010a71e52d590a5039b4849fa4"
-    , "34a0aafb95917cbf8c38fc5548373c05"
-    , "0407b7c57bc11361747c3d67526c36e228028a5d0b145d66ab9a2fe4b07507a0"
-    , ""
-    , ""
-    , "299aba0661315211b09d2861855d0b4b125ab24649461341af6abd903ed6f025223b3299f2126fcad44c675166d800619cf49540946b12138989417904324b0ddad121327211a297f11259c9c34ce4c70c322a653675f78d385e4e2443f8058d141195e17e0bd1b9d44bf3e48c376e6eb44ef020b11cf03eb141c46ecb43cf3d"
-    ],
-    -- COUNT = 7
-    [ "9ae3506aadbc8358696ba1ba17e876e1157b7048235921503d36d9211b430342"
-    , "9abf7d66afee5d2b811cba358bbc527d"
-    , "0d645f6238e9ceb038e4af9772426ca110c5be052f8673b8b5a65c4e53d2f519"
-    , ""
-    , ""
-    , "5f032c7fec6320fe423b6f38085cbad59d826085afe915247b3d546c4c6b174554dd4877c0d671de9554b505393a44e71f209b70f991ac8aa6e08f983fff2a4c817b0cd26c12b2c929378506489a75b2025b358cb5d0400821e7e252ac6376cd94a40c911a7ed8b6087e3de5fa39fa6b314c3ba1c593b864ce4ff281a97c325b"
-    ],
-    -- COUNT = 8
-    [ "96ae3b8775b36da2a29b889ad878941f43c7d51295d47440cd0e3c4999193109"
-    , "1fe022a6fc0237b055d4d6a7036b18d5"
-    , "1e40e97362d0a823d3964c26b81ab53825c56446c5261689011886f19b08e5c2"
-    , ""
-    , ""
-    , "e707cd14b06ce1e6dbcceaedbf08d88891b03f44ad6a797bd12fdeb557d0151df9346a028dec004844ca46adec3051dafb345895fa9f4604d8a13c8ff66ae093fa63c4d9c0816d55a0066d31e8404c841e87b6b2c7b5ae9d7afb6840c2f7b441bf2d3d8bd3f40349c1c014347c1979213c76103e0bece26ad7720601eff42275"
-    ],
-    -- COUNT = 9
-    [ "33f5120396336e51ee3b0b619b5f873db05ca57cda86aeae2964f51480d14992"
-    , "6f1f6e9807ba5393edcf3cb4e4bb6113"
-    , "3709605af44d90196867c927512aa8ba31837063337b4879408d91a05c8efa9f"
-    , ""
-    , ""
-    , "8b8291126ded9acef12516025c99ccce225d844308b584b872c903c7bc6467599a1cead003dc4c70f6d519f5b51ce0da57f53da90dbe8f666a1a1dde297727fee2d44cebd1301fc1ca75956a3fcae0d374e0df6009b668fd21638d2b733e6902d22d5bfb4af1b455975e08eef0ebe4dc87705801e7776583c8de11672729f723"
-    ],
-    -- COUNT = 10
-    [ "ad300b799005f290fee7f930eebce158b98fb6cb449987fe433f955456b35300"
-    , "06aa2514e4bd114edf7ac105cfef2772"
-    , "87ada711465e4169da2a74c931afb9b5a5b190d07b7af342aa99570401c3ee8a"
-    , ""
-    , ""
-    , "80d7c606ff49415a3a92ba1f2943235c01339c8f9cd0b0511fbfdf3ef23c42ffff008524193faaa4b7f2f2eb0cfa221d9df89bd373fe4e158ec06fad3ecf1eb48b8239b0bb826ee69d773883a3e8edac66254610ff70b6609836860e39ea1f3bfa04596fee1f2baca6cebb244774c6c3eb4af1f02899eba8f4188f91776de16f"
-    ],
-    -- COUNT = 11
-    [ "130b044e2c15ab89375e54b72e7baae6d4cad734b013a090f4df057e634f6ff0"
-    , "65fd6ac602cd44107d705dbc066e52b6"
-    , "f374aba16f34d54aae5e494505b67d3818ef1c08ea24967a76876d4361379aec"
-    , ""
-    , ""
-    , "5d179534fb0dba3526993ed8e27ec9f915183d967336bb24352c67f4ab5d7935d3168e57008da851515efbaecb69904b6d899d3bfa6e9805659aef2942c4903875b8fcbc0d1d24d1c075f0ff667c1fc240d8b410dff582fa71fa30878955ce2ed786ef32ef852706e62439b69921f26e84e0f54f62b938f04905f05fcd7c2204"
-    ],
-    -- COUNT = 12
-    [ "716430e999964b35459c17921fe5f60e09bd9ab234cb8f4ba4932bec4a60a1d5"
-    , "9533b711e061b07d505da707cafbca03"
-    , "372ae616d1a1fc45c5aecad0939c49b9e01c93bfb40c835eebd837af747f079d"
-    , ""
-    , ""
-    , "a80d6a1b2d0ce01fe0d26e70fb73da20d45841cf01bfbd50b90d2751a46114c0e758cb787d281a0a9cf62f5c8ce2ee7ca74fefff330efe74926acca6d6f0646e4e3c1a1e52fce1d57b88beda4a5815896f25f38a652cc240deb582921c8b1d03a1da966dd04c2e7eee274df2cd1837096b9f7a0d89a82434076bc30173229a60"
-    ],
-    -- COUNT = 13
-    [ "7679f154296e6d580854826539003a82d1c54e2e062c619d00da6c6ac820789b"
-    , "55d12941b0896462e7d888e5322a99a3"
-    , "ba4d1ed696f58ef64596c76cee87cc1ca83069a79e7982b9a06f9d62f4209faf"
-    , ""
-    , ""
-    , "10dc7cd2bb68c2c28f76d1b04ae2aa287071e04c3b688e1986b05cc1209f691daa55868ebb05b633c75a40a32b49663185fe5bb8f906008347ef51590530948b87613920014802e5864e0758f012e1eae31f0c4c031ef823aecfb2f8a73aaa946fc507037f9050b277bdeaa023123f9d22da1606e82cb7e56de34bf009eccb46"
-    ],
-    -- COUNT = 14
-    [ "8ca4a964e1ff68753db86753d09222e09b888b500be46f2a3830afa9172a1d6d"
-    , "a59394e0af764e2f21cf751f623ffa6c"
-    , "eb8164b3bf6c1750a8de8528af16cffdf400856d82260acd5958894a98afeed5"
-    , ""
-    , ""
-    , "fc5701b508f0264f4fdb88414768e1afb0a5b445400dcfdeddd0eba67b4fea8c056d79a69fd050759fb3d626b29adb8438326fd583f1ba0475ce7707bd294ab01743d077605866425b1cbd0f6c7bba972b30fbe9fce0a719b044fcc1394354895a9f8304a2b5101909808ddfdf66df6237142b6566588e4e1e8949b90c27fc1f"
-    ]
-    ]
-
-{-
-    [SHA-256]
-    [PredictionResistance = False]
-    [EntropyInputLen = 256]
-    [NonceLen = 128]
-    [PersonalizationStringLen = 256]
-    [AdditionalInputLen = 256]
-    [ReturnedBitsLen = 1024]
--}
-
-t4 :: [TestVector]
-t4 =
-    [
-    -- COUNT = 0
-    [ "5d3286bc53a258a53ba781e2c4dcd79a790e43bbe0e89fb3eed39086be34174b"
-    , "c5422294b7318952ace7055ab7570abf"
-    , "2dba094d008e150d51c4135bb2f03dcde9cbf3468a12908a1b025c120c985b9d"
-    , "793a7ef8f6f0482beac542bb785c10f8b7b406a4de92667ab168ecc2cf7573c6"
-    , "2238cdb4e23d629fe0c2a83dd8d5144ce1a6229ef41dabe2a99ff722e510b530"
-    , "d04678198ae7e1aeb435b45291458ffde0891560748b43330eaf866b5a6385e74c6fa5a5a44bdb284d436e98d244018d6acedcdfa2e9f499d8089e4db86ae89a6ab2d19cb705e2f048f97fb597f04106a1fa6a1416ad3d859118e079a0c319eb95686f4cbcce3b5101c7a0b010ef029c4ef6d06cdfac97efb9773891688c37cf"
-    ],
-    -- COUNT = 1
-    [ "c2a566a9a1817b15c5c3b778177ac87c24e797be0a845f11c2fe399dd37732f2"
-    , "cb1894eb2b97b3c56e628329516f86ec"
-    , "13ce4d8dd2db9796f94156c8e8f0769b0aa1c82c1323b61536603bca37c9ee29"
-    , "413dd83fe56835abd478cb9693d67635901c40239a266462d3133b83e49c820b"
-    , "d5c4a71f9d6d95a1bedf0bd2247c277d1f84a4e57a4a8825b82a2d097de63ef1"
-    , "b3a3698d777699a0dd9fa3f0a9fa57832d3cefac5df24437c6d73a0fe41040f1729038aef1e926352ea59de120bfb7b073183a34106efed6278ff8ad844ba0448115dfddf3319a82de6bb11d80bd871a9acd35c73645e1270fb9fe4fa88ec0e465409ea0cba809fe2f45e04943a2e396bbb7dd2f4e0795303524cc9cc5ea54a1"
-    ],
-    -- COUNT = 2
-    [ "a33288a96f41dd54b945e060c8bd0c094f1e28267cc1dcbba52063c1a9d54c4d"
-    , "36918c977e1a7276a2bb475591c367b7"
-    , "6aa528c940962638dc2201738850fd1fe6f5d0eb9f687ff1af39d9c7b36830d9"
-    , "37ee633a635e43af59abdb1762c7ea45bfe060ec1d9077ecd2a43a658673f3c7"
-    , "2eb96f2e28fa9f674bb03ade703b8f791ee5356e2ee85c7ed5bda96325256c61"
-    , "db2f91932767eb846961ce5321c7003431870508e8c6f8d432ca1f9cee5cdc1aed6e0f133d317eb6990c4b3b0a360cdfb5b43a6e712bd46bca04c414868fab22c6a49c4b89c812697c3a7fbfc8ddf10c8aa5ebf13a09fd114eb2a02a07f69786f3ce7fd30231f22779bc8db103b13fa546dbc45a89a86275281172761683d384"
-    ],
-    -- COUNT = 3
-    [ "5f37b6e47e1776e735adc03d4b999879477ff4a206231924033d94c0114f911b"
-    , "7d12d62c79c9f6234ae0314156947459"
-    , "92d4d9fab5f8bf5119f2663a9df7334f50dcde74fb9d7732f7eba56501e60d54"
-    , "c9aef0d7a9ba7345d08b6d5b5ce5645c7495b8685e6b93846ffcf470f5abd40d"
-    , "50d9d1f5074f7d9f1a24a9c63aa47b94da5ba78db1b0f18e4d4fe45c6875813c"
-    , "20d942bbd7d98700faa37e94d53bf74f2d6bd1d8c95c0b88d842c4857797d59e7c8788aeeac29740122f208f703bf35dc32b0035db0648384feb6aa17a3274bc09b2d2b746c5a06fd82f4469fb86131a49482cb7be7d9b4b95042394cfb18b13f333ec0fe5c227bf1d8f33ecb2e42e358b6c3e034cb585331bd1d27f638029b9"
-    ],
-    -- COUNT = 4
-    [ "2311c5afd64c584484b2729e84db80c0b4063fe9ca7edc83350488d7e67264a0"
-    , "6a6dfd975a0dc7b72df1f107c4b3b3a6"
-    , "2abd870ec5fe26ed14dfa57a3309f920131b70580c3639af2645cd1af93db1b1"
-    , "c6e532a3b25653b6002aed5269cc2118749306e736bde039d4d569d4f967773f"
-    , "5e7d26c4da769c373092b2b4f72b109fe34bdb7d169ea38f78ebae5df4a15759"
-    , "cacaeb1b4ac2305d8714eb50cbe1c67c5a2c0bbc7938fdfdcafef7c85fc40becbf777a4cfb6f14c6eee320943a493d2b0a744a6eb3c256ee9a3763037437df9adce3e2260f0c35e958af0edb5a81debd8bdaf2b8bb2b98b9186e5a222a21609ff58df4cbe1d4898d10d6e7c46f31f5cb1041bfd83a5fb27d5c56c961e91403fc"
-    ],
-    -- COUNT = 5
-    [ "362ece9d330e1172a8f9e50258476d0c79c3ee50346524ba12d970ee3a6ef8c5"
-    , "cf11bcb4d9d51311ceacfca8705e833f"
-    , "abb5a8edde02e526449284ecc31bc713383df3ed085f752e3b6a32f305861eed"
-    , "746302ab1f4a86b17546bea762e929360f2e95c7788a63545a264ef997c8c65e"
-    , "b907c5b2a8833a48e56e819228ce9a050b41b3309f5ca37bed720311d92b33af"
-    , "73c7131a558350590053580873ef956ff952f2aa6ff1bea452e013d1bc2afddea2311756dbe756e63ba6258480c48f3f6c1319b5f572f67ca530af09e39413d1d432bea8f89206619618cb0e7c88e9f2033639d0eb0efc20616b64f940da99b88231984c3fb23f19e890576f555fde394dbd4351f17a7ffd5c369379001bda03"
-    ],
-    -- COUNT = 6
-    [ "cf614bc29946bc0095f415e8bdeda10aab05392f9cc9187a86ea6ec95ee422e1"
-    , "77fb5ec22dc0432cc13f4693e2e3bd9a"
-    , "e4ce77914ffbc5fddf1fb51edfafdc196109139b84c741354135ec8d314c7c43"
-    , "e1e83ee1205acaf6164dc287aec08e5b32789e5be818078db39e53cad589db51"
-    , "4e20c0226d5e1e7e805679f03f72452b5bea2d0ba41e0c12329bf60eb3016dd1"
-    , "838fdf1418a746aa52ae4005d90c3fd301f648c5770ffef2a9f3912e37a93850cc4b8bfcce910aead0cb75958823b1a62e283901c5e4a3980e4ea36257458e2e4953555819b8852a26489b1d74821f80c9908469b43f124ff7ea62497c36159a47353098a1b9ec32e54800d6704371cc37f357ad74aacc203e9b6db97f94d0c4"
-    ],
-    -- COUNT = 7
-    [ "a8da1d3e233f393fd44d204c200202f7d01896e72c5ac652940cfd15b5d4b0bd"
-    , "0a112b4cb0890af0a495e0f49fcf6874"
-    , "d2e32799bc822b8d033299bdf63dc35774f7649e935d25be5b10512c430d1bda"
-    , "920a82d76fcd2cd106ada64bba232b7b2344f3afe6b1d1d20ee8795144571009"
-    , "eeaac5878275372025f8231febed64db6a11273c3c00d625fc80a95f18ad7d3f"
-    , "5f6dae489b53d89027b2cc333c700f090152d77b3eaf01d47f56ce6eca9893ef877b4cb560fab0fbdb34e3d1c6cd8480b33c053d2661a10aa531df4961b97d659c7492584236582b3fe701055efa59c328194cd1e07fcffd910d9ee01b7b9e8c8fda7f7ac01a8e203b8b26eb8078a9b9a5021562c44af24089e3ef84c1d5a6bd"
-    ],
-    -- COUNT = 8
-    [ "a77b1ed4ecaa650374e1052c405f1d88881c25c87d13dbe1334d8c1a847fa76b"
-    , "05c143e2f145db216fe7be9ed23635d0"
-    , "b5c750968ff09ed251d4a1c05342ac843db5246b19045728a634fa4f6e752e54"
-    , "ff5937bcd01a363696bf8e40adc8e4ab3e56dbf7e7d09451c99e538785fe6697"
-    , "4acb34eea8266badcf8f6557a0eecf3eb4d7a295c876d6175598cb66a388efb8"
-    , "ec13eadfcc84e77d2a2efa1a2cd8b1355587cb27feb3d19d75b37f0446333ddb8236e751c63b7a6e595ec24a25051a696dbe8c062dd8896d1446db228a2f10e8094ee07e7ee648ed6bebb2f5ec5aae24c9c640665c28355cc11c116795ecc070790f7fdfc4398900311b6695d5da0175091ed1828d2731085bfb4a20bd86cce0"
-    ],
-    -- COUNT = 9
-    [ "491686c781e83eb4e21d9989e8d718100b0d21a2c56295888baef1a65f219651"
-    , "499085296d21065feabf3106101c8d6f"
-    , "d208a72f9ae34f0817669fb04f49239dd31700f3dc9a93db8d75fb79f9b686c1"
-    , "9ffc61893a293a864008fdd56d3292600d9e2ec8a1ea8f34ac5931e968905a23"
-    , "4ff3a397dfdae0912032a302a5e7a07dceca8d9013a21545689319b7c024cd07"
-    , "3c258ebf2203fca3b322ad1b016e21c7f5c148425f81e4fb0a0e462dce9dfa569c37a006527768297a5b68461b08912642a341b88c85597e30e7561206886098c4e2d861f11513f0ffdbbc78d3a2dd60c105abbb33c5e05ae27081b690fb8b3610917aa9bf1a4ad74481b5ff8334f14e5ad6a6a1eb2259476078076fb7e3a992"
-    ],
-    -- COUNT = 10
-    [ "36a5267eeeb5a1a7d46de0f8f9281f73cd9611f01198fdaa78c5315205e5a177"
-    , "b66b5337970df36219321badacc624eb"
-    , "c2a7b164949da102bece44a423197682ff97627d1fe9654266b8527f64e5b386"
-    , "a977e2d8637b019c74063d163bb25387dc56f4eb40e502cefc5ae6ad26a6abdc"
-    , "c5c9819557b1e7d8a86fa8c60be42993edc3ef539c13d9a51fb64b0de06e145e"
-    , "b471711a4fc7ab7247e65d2c2fe49a50169187187b7978cd2fdb0f8318be3ec55fc68ed4577ad9b42cbb57100b5d35ac86c244c4c93a5b28c1a11c2dfe905d608ec7804dec5bb15cf8d79695534d5e13a6a7e18a887ec9cf184da0cbbc6267f3a952a769403bafcdbb559401be0d8b3300ea7258b4026fc892175efd55ba1a67"
-    ],
-    -- COUNT = 11
-    [ "a76b0366df89e4073a6b6b9c04da1d6817ce26f1c4825cad4097bdf4d7b9445e"
-    , "773d3cc3290176773847869be528d1a4"
-    , "1bfd3bcfb9287a5ad055d1b2b8615fa81c94ac24bc1c219a0f8de58789e0404a"
-    , "edd879fa56f21d93029da875b683ce50f6fdc4c0da41da051d000eed2afefefa"
-    , "f528ffd29160039260133ed9654589ce60e39e7f667c34f82cda65ddcf5fff14"
-    , "39d1ff8848e74dd2cdc6b818ad69823878062116fdf1679942f892c7e191be1c4b6ea268ecdff001b22af0d510f30c2c25b90fc34927f46e3f45d36b0e1848b3a5d54c36c7c65ee7287d325dfbb51b56a438feb6650ce13df88bf06b87ac4a35d2a199ea888629fb0d83f82f0ea160dc79ed220d8ef195b9e80c542f60c2d320"
-    ],
-    -- COUNT = 12
-    [ "46571e1df43e5e141235e2a9ec85bb0faf1dc0566031e14d41a2fbd0315653ec"
-    , "b60ef6a3347967519aabeaf748e4e991"
-    , "759fd8593e3688b23c4a003b655311770d670789878570eb3b155a8e6c2d8c45"
-    , "033128460b449e1accb0e9c54508759ddc2538bc64b51e6277553f0c60a02723"
-    , "a5e4a717240bdeac18a0c0e231a11dc04a47d7550f342fa9a7a5ff334eb9327d"
-    , "9d222df1d530ea7f8f2297a0c79d637da570b48042ecddded75956bba0f0e70b271ffa3c9a53bada6ee1b8a4203c22bfde82a5e2eb1b150f54c6483458569422c1a34a8997d42cc09750167a78bf52a0bd158397af9f83caabe689185c099bf0a9a4853dd3cf8b8e89efebb6a27dba873e65e9927741b22968f2875789b44e01"
-    ],
-    -- COUNT = 13
-    [ "d63980e63bbe4ac08d2ac5646bf085b82c75995e3fdfc23bb9cc734cd85ca7d2"
-    , "d33ed1dcae13fb634ba08272d6697590"
-    , "acd0da070072a5340c4f5f4395568e1a36374e074196ae87f3692ee40487e1df"
-    , "f567677b5e12e26f3544be3da9314c88fc475bf84804a89a51f12b191392c02b"
-    , "c01cc7873e93c86e2bfb8fc984cfc2eab5cc58eeef018fedb5cba5aedd386156"
-    , "b133446f633bcb40724bbf9fa187c39a44b9c094a0a0d40e98977e5466dc2c9adf62a5f4551eeb6406a14658de8a0ed7487c3bf6277e811101284a941745ce16176acc875f1435e14161772fa84609e8123c53dd03cbb868030835c0d11d8d6aa04a1b6f908248b028997737f54735ec4ed7a81fc868199ffb61a779d9340334"
-    ],
-    -- COUNT = 14
-    [ "3d99f9b7ac3a2fbe9cf15d960bf41f5588fc4db1e0d2a5c9c0fe9059f03593fb"
-    , "411f504bb63a9b3afa7ffa1357bb48be"
-    , "0bb5ebd55981a25ba69164da49fa92f2871fd3fc65eb30d0f0d0b8d798a4f8f2"
-    , "288e948a551284eb3cb23e26299955c2fb8f063c132a92683c1615ecaed80f30"
-    , "d975b22f79e34acf5db25a2a167ef60a10682dd9964e15533d75f7fa9efc5dcb"
-    , "ee8d707eea9bc7080d58768c8c64a991606bb808600cafab834db8bc884f866941b4a7eb8d0334d876c0f1151bccc7ce8970593dad0c1809075ce6dbca54c4d4667227331eeac97f83ccb76901762f153c5e8562a8ccf12c8a1f2f480ec6f1975ac097a49770219107d4edea54fb5ee23a8403874929d073d7ef0526a647011a"
-    ]
-    ]
-
-{- Reseed test vectors -}
-
-{-
-    [SHA-256]
-    [PredictionResistance = False]
-    [EntropyInputLen = 256]
-    [NonceLen = 128]
-    [PersonalizationStringLen = 0]
-    [AdditionalInputLen = 0]
-    [ReturnedBitsLen = 1024]
--}
-
-r1 :: [TestVector]
-r1 =
-    [
-    -- COUNT = 0
-    [ "06032cd5eed33f39265f49ecb142c511da9aff2af71203bffaf34a9ca5bd9c0d"
-    , "0e66f71edc43e42a45ad3c6fc6cdc4df"
-    , ""
-    , "01920a4e669ed3a85ae8a33b35a74ad7fb2a6bb4cf395ce00334a9c9a5a5d552"
-    , ""
-    , ""
-    , ""
-    , "76fc79fe9b50beccc991a11b5635783a83536add03c157fb30645e611c2898bb2b1bc215000209208cd506cb28da2a51bdb03826aaf2bd2335d576d519160842e7158ad0949d1a9ec3e66ea1b1a064b005de914eac2e9d4f2d72a8616a80225422918250ff66a41bd2f864a6a38cc5b6499dc43f7f2bd09e1e0f8f5885935124"
-    ],
-    -- COUNT = 1
-    [ "aadcf337788bb8ac01976640726bc51635d417777fe6939eded9ccc8a378c76a"
-    , "9ccc9d80c89ac55a8cfe0f99942f5a4d"
-    , ""
-    , "03a57792547e0c98ea1776e4ba80c007346296a56a270a35fd9ea2845c7e81e2"
-    , ""
-    , ""
-    , ""
-    , "17d09f40a43771f4a2f0db327df637dea972bfff30c98ebc8842dc7a9e3d681c61902f71bffaf5093607fbfba9674a70d048e562ee88f027f630a78522ec6f706bb44ae130e05c8d7eac668bf6980d99b4c0242946452399cb032cc6f9fd96284709bd2fa565b9eb9f2004be6c9ea9ff9128c3f93b60dc30c5fc8587a10de68c"
-    ],
-    -- COUNT = 2
-    [ "62cda441dd802c7652c00b99cac3652a64fc75388dc9adcf763530ac31df9214"
-    , "5fdc897a0c1c482204ef07e0805c014b"
-    , ""
-    , "bd9bbf717467bf4b5db2aa344dd0d90997c8201b2265f4451270128f5ac05a1a"
-    , ""
-    , ""
-    , ""
-    , "7e41f9647a5e6750eb8acf13a02f23f3be77611e51992cedb6602c314531aff2a6e4c557da0777d4e85faefcb143f1a92e0dbac8de8b885ced62a124f0b10620f1409ae87e228994b830eca638ccdceedd3fcd07d024b646704f44d5d9c4c3a7b705f37104b45b9cfc2d933ae43c12f53e3e6f798c51be5f640115d45cf919a4"
-    ],
-    -- COUNT = 3
-    [ "6bdc6ca8eef0e3533abd02580ebbc8a92f382c5b1c8e3eaa12566ecfb90389a3"
-    , "8f8481cc7735827477e0e4acb7f4a0fa"
-    , ""
-    , "72eca6f1560720e6bd1ff0152c12eeff1f959462fd62c72b7dde96abcb7f79fb"
-    , ""
-    , ""
-    , ""
-    , "d5a2e2f254b5ae65590d4fd1ff5c758e425be4bacdeede7989669f0a22d34274fdfc2bf87135e30abdae2691629c2f6f425bd4e119904d4785ecd9328f15259563e5a71f915ec0c02b66655471067b01016fdf934a47b017e07c21332641400bbe5719050dba22c020b9b2d2cdb933dbc70f76fec4b1d83980fd1a13c4565836"
-    ],
-    -- COUNT = 4
-    [ "096ef37294d369face1add3eb8b425895e921626495705c5a03ee566b34158ec"
-    , "6e2e0825534d2989715cc85956e0148d"
-    , ""
-    , "1b4f7125f472c253837fa787d5acf0382a3b89c3f41c211d263052402dcc62c5"
-    , ""
-    , ""
-    , ""
-    , "4541f24f759b5f2ac2b57b51125077cc740b3859a719a9bab1196e6c0ca2bd057af9d3892386a1813fc8875d8d364f15e7fd69d1cc6659470415278164df656295ba9cfcee79f6cbe26ee136e6b45ec224ad379c6079b10a2e0cb5f7f785ef0ab7a7c3fcd9cb6506054d20e2f3ec610cbba9b045a248af56e4f6d3f0c8d96a23"
-    ],
-    -- COUNT = 5
-    [ "a7dccdd431ae5726b83585b54eae4108f7b7a25c70187c0acbb94c96cc277aa8"
-    , "94c8f4b8e195a47356a89a50d1389ab5"
-    , ""
-    , "51733eee2e922f4055e53939e222e71fae730eb037443db2c7679708abb86a65"
-    , ""
-    , ""
-    , ""
-    , "99ba2691a622afecc9472418e6a8f9f1cdc1e3583c3bc7a2a650a1ab79dcbccbd656636c573179276e782569420c97438c06be898867f628b1c01eb570263d2c0f09c7aab536f6fba7df6aad19e05c236b645674667c03d1b6a04d7fc11177fe78933b309679f5bf26a4632b9a13e314c4bf4532428d3d95c689002b6dc1fbb1"
-    ],
-    -- COUNT = 6
-    [ "c286425ecf543a49bcc9196b0db1a80bc54e4948adba6f41712a350a02891fa6"
-    , "957a659a4ec2e0b7ad185483c220fd61"
-    , ""
-    , "08c2129813eea0776fba72788fdf2718759cc3c4207fa20a5fe23ac6e32cc28e"
-    , ""
-    , ""
-    , ""
-    , "8e1020a4fd84c99e0fc7e3f7ce48de5ed9ec9a5c2ccd624dbe6f30e2f688a31dc55957630357a5d48ca2a456241a28bfb16d8bb000877697a7ce24d9ad4d22b0c15117996f1f270b94f46d7a9bdfa7608fa1dd849177a9b8049e51b6b7a2742623854a1fddb5efc447eed1ea1aed6f02b4b2754ecf71ea0509da2e54f524a7e7"
-    ],
-    -- COUNT = 7
-    [ "02818bd7c1ec456ace55beeba99f646a6d3aa0ea78356ea726b763ff0dd2d656"
-    , "c482687d508c9b5c2a75f7ce390014e8"
-    , ""
-    , "cf319bfa63980e3cb997fd28771bb5614e3acb1149ba45c133ffbbab17433193"
-    , ""
-    , ""
-    , ""
-    , "19a231ff26c1865ce75d7a7185c30dd0b333126433d0c8cbf1be0d2b384d4eb3a8aff03540fbfa5f5496521a4e4a64071b44c78bd0b7e68fac9e5695c5c13fd3b9dbe7f7739781a4c8f0b980f1b17d99bce17ceb52b56866ae02456ffef83399c8cf7826f3c45c8a19315890919d20f40fc4e18d07e9c8ccd16c3327b5988f71"
-    ],
-    -- COUNT = 8
-    [ "77a5c86d99be7bc2502870f4025f9f7563e9174ec67c5f481f21fcf2b41cae4b"
-    , "ed044ad72ee822506a6d0b1211502967"
-    , ""
-    , "778100749f01a4d35c3b4a958aafe296877e0acafd089f50bc7797a42a33ab71"
-    , ""
-    , ""
-    , ""
-    , "831a4da566f46289904893ef1cc1cd4ad19ee48f3857e2b69e936d10afbdc29822e85d02663d346ef3e09a848b1d9cc04f4c4c6e3b3b0e56a034e2334d34ca08f8097be307ba41d020bc94f8c1937fe85644eeb5592c2b5a2138f7ded9a5b44b200c8b5beb27597c790f94d660eb61e8248391edc3ae2d77656cbe8354275b13"
-    ],
-    -- COUNT = 9
-    [ "0ea458cff8bfd1dd8b1addcba9c01317d53039e533104e32f96e7d342e6c7b9b"
-    , "935a4b66fc74c2a48757a99c399e64e3"
-    , ""
-    , "6c5f3708e7b714c4ed139b4fa9e8c763af01773484005109a85e33653bb0ce98"
-    , ""
-    , ""
-    , ""
-    , "373a37af84fddec13645a9768d6a785ae5a2589d64cd9b37980dde2541499210c4f408335de1d585349064f3f53a2b4c5ec6dc2a09591f99ad9fad528ac83474164b45497bf167f81e66fa08463ffea917f6891e48f149fafc20622bb1172f34886feb45c26fd446a4a4e2891b4bc594186896141aaaeeb301b49e7c1a26fec7"
-    ],
-    -- COUNT = 10
-    [ "bfb68be4ce1756d25bdfad5e0c2f8bec29360901cc4da51d423d1591cc57e1ba"
-    , "98afe4bd194c143e099680c504cceaab"
-    , ""
-    , "b97caf210e82498c3408790d41c320dd4a72007778389b44b7bc3c1c4b8c53f8"
-    , ""
-    , ""
-    , ""
-    , "409e0aa949fb3b38231bf8732e7959e943a338ea399026b744df15cbfeff8d71b3da023dcce059a88cf0d4b7475f628e4764c8bef13c70cfbbbb6da2a18aabcad919db09d04fc59765edb165147c88dd473a0f3c5ee19237ca955697e001ba654c5ee0bd26761b49333154426bc63286298a8be634fe0d72cfdeef0f3fc48eca"
-    ],
-    -- COUNT = 11
-    [ "4f6880a64610004463031d67d7924fa446c39138d4d41007e8df3d65691a9367"
-    , "6b33b2c13600f4b1df6ca3d1960e8dd4"
-    , ""
-    , "57b87b8c8f48312b5333d43b367730c0a5ad4725a16778fcb53fe136d136cbfd"
-    , ""
-    , ""
-    , ""
-    , "73d0f324ed186e2ad06bd1800e262bdbda79ba54e626761bd60f74f43e3bb62958ec1e2f1d940af163e1cadc124e7ebaba2f72e67efd746c7f6d0cad53ef03d859d93cff778a32ee5be172fe7fdbdc232ded360d704a6fa0f70bebe942e56478345492f49dc5c6fc346b88a58947ad250e688e8c626fe1efe7624620e571976e"
-    ],
-    -- COUNT = 12
-    [ "aae352e111843219cae8f70e7b8f6eb9bb53d246cbec1e4f07d42757143295b4"
-    , "b84485dccd1bf93210e322eafcbebcd9"
-    , ""
-    , "f9237f00d744d8fbff21b9d0043c258e8731817e6a5fb7b4bf5011680e5bc642"
-    , ""
-    , ""
-    , ""
-    , "cfb28b93522c7d61d8d3ce3f080e435e4c83c7e13a9dab788db8fef0407267a14fbc9324e090e24df5491fedfa81116869983938d4d4d7324a310c3af33a6f7938f602c5e4e63f1771cdaabdab0782b5affb54eb53047c109a9606739dd0065bd21eca33132986554878354f5f9f852e674dd690163b0ff74c7a25e6bae8ce39"
-    ],
-    -- COUNT = 13
-    [ "589e79e339b7d2a1b879f0b0e1a7d1ad2474eaa8025b070f1ffa877b7124d4ff"
-    , "0961ed64dbd62065d96e75de6d2ff9d6"
-    , ""
-    , "e928388d3af48c2968527a4d2f9c2626fbc3f3f5a5d84e0583ab6f78e7f8b081"
-    , ""
-    , ""
-    , ""
-    , "fce6ced1ecf474d181ab331f79c3d2cc8a768ec2818de5b3fc7cf418322716d6a6853733561a497c0c25cb288d2c9fcfbca891bafd5a834c85f3603f402acf1a7b1ea92db847ed5c252a862ad4ab5e259715f1fc81da67f5230bf8be50ee8069758095f7d0e559e03f2c6072290e61794458437609e473eb66580cddaad19b71"
-    ],
-    -- COUNT = 14
-    [ "714277d408ad87fde317f0a94732fce62f1352bdc90936673b4f1daa0925aa26"
-    , "d16582a99f23010b4248b88d86485419"
-    , ""
-    , "bd9fc7cb2fd5063b2c3c0c4f346ad2e3879371a9c805e59b9f2cd2cc2a40894f"
-    , ""
-    , ""
-    , ""
-    , "62ef7a431288252e0d736c1d4e36cc9ac37107dcd0d0e971a22444a4adae73a41eff0b11c8625e118dbc9226142fd0a6aa10ac9b190919bda44e7248d6c88874612abd77fb3716ea515a2d563237c446e2a282e7c3b0a3aef27d3427cc7d0a7d38714659c3401dbc91d3595159318ebca01ae7d7fd1c89f6ad6b604173b0c744"
-    ]
-    ]
-
-{-
-    [SHA-256]
-    [PredictionResistance = False]
-    [EntropyInputLen = 256]
-    [NonceLen = 128]
-    [PersonalizationStringLen = 0]
-    [AdditionalInputLen = 256]
-    [ReturnedBitsLen = 1024]
--}
-
-r2 :: [TestVector]
-r2 =
-    [
-    -- COUNT = 0
-    [ "05ac9fc4c62a02e3f90840da5616218c6de5743d66b8e0fbf833759c5928b53d"
-    , "2b89a17904922ed8f017a63044848545"
-    , ""
-    , "2791126b8b52ee1fd9392a0a13e0083bed4186dc649b739607ac70ec8dcecf9b"
-    , "43bac13bae715092cf7eb280a2e10a962faf7233c41412f69bc74a35a584e54c"
-    , "3f2fed4b68d506ecefa21f3f5bb907beb0f17dbc30f6ffbba5e5861408c53a1e"
-    , "529030df50f410985fde068df82b935ec23d839cb4b269414c0ede6cffea5b68"
-    , "02ddff5173da2fcffa10215b030d660d61179e61ecc22609b1151a75f1cbcbb4363c3a89299b4b63aca5e581e73c860491010aa35de3337cc6c09ebec8c91a6287586f3a74d9694b462d2720ea2e11bbd02af33adefb4a16e6b370fa0effd57d607547bdcfbb7831f54de7073ad2a7da987a0016a82fa958779a168674b56524"
-    ],
-    -- COUNT = 1
-    [ "1bea3296f24e9242b96ed00648ac6255007c91f7c1a5088b2482c28c834942bf"
-    , "71073136a5cc1eb5b5fa09e1790a0bed"
-    , ""
-    , "d714329f3fbea1df9d0b0b0d88dfe3774beb63d011935923d048e521b710dc6f"
-    , "4ef872fd211a426ea1085ab39eb220cc698fdfeabe49b8835d620ab7885de7a4"
-    , "d74d1669e89875852d9ccbf11c20fe3c13a621ebcb3f7edeea39a2b3379fdcf5"
-    , "0c8aa67ca310bd8e58c16aba35880f747266dbf624e88ec8f9ee9be5d08fdeb1"
-    , "ce95b98f13adcdf7a32aa34709d6e02f658ae498d2ab01ce920f69e7e42c4be1d005acf0ca6b17891dfafc620dd4cd3894f8492a5c846089b9b452483eb0b91f3649ec0b6f98d1aaabc2e42cd39c2b25081b85ab50cb723007a0fd83550f32c210b7c4150b5a6bb3b0c9e3c971a09d43acb48e410a77f824b957092aa8ef98bc"
-    ],
-    -- COUNT = 2
-    [ "a7ea449b49db48601fc3a3d5d77081fab092b8d420ed1b266f704f94352dd726"
-    , "d11a159b60af8d20a0e37d27e6c74aa3"
-    , ""
-    , "50916ab47e8cb5dc843f9fba80639103711f86be8e3aa94f8a64a3fe0e6e5b35"
-    , "e2bb6768120555e7b9e0d573537a82f8f32f54560e1050b6abb1588fb3441e66"
-    , "a50cec9d1ecddb2c163d24019e81c31a2b350ccd3ad8181fd31bb8d1f64fa50e"
-    , "591dbbd48b51abced67f9c6269cf0133cd3dcbb5cfafcb6ef758569c555a5773"
-    , "0a464abcc8685158372d544635b953fcb1d3821c30aaa93982f9b788935f00f88115aad61d5cee003b3d1cb50f3e961a501e2dd0fc7e1724778b184a4bdf9f64e110dda7446e5544a30bd49a400ea1a5411800e1edfeea349323618afc5dc5782dc4b71d2da4d6a4785f8dd346feb9c8740ffd26bf644e3e4323ff24c30b9f10"
-    ],
-    -- COUNT = 3
-    [ "14683ec508a29d7812e0f04a3e9d87897000dc07b4fbcfda58eb7cdabc492e58"
-    , "b2243e744eb980b3ece25ce76383fd46"
-    , ""
-    , "18590e0ef4ee2bdae462f76d9324b3002559f74c370cfccf96a571d6955703a7"
-    , "9ea3ccca1e8d791d22fcda621fc4d51b882df32d94ea8f20ee449313e6909b78"
-    , "16366a578b5ea4d0cb547790ef5b4fd45d7cd845bc8a7c45e99419c8737debb4"
-    , "a68caa29a53f1ba857e484d095805dc319fe6963e4c4daaf355f722eba746b92"
-    , "c4e7532ee816789c2d3da9ff9f4b37139a8515dbf8f9e1d0bf00c12addd79ebbd76236f75f2aa705a09f7955038ebff0d566911c5ea13214e2c2eeb46d23ad86a33b60f7b9448d63eec3e1d59f48b39552857447dc5d7944667a230e3dbfa30ca322f6eacaf7536a286706a627c5083c32de0658b9073857c30fb1d86eb8ad1b"
-    ],
-    -- COUNT = 4
-    [ "fa261fb230e2822458532ca2d5c39758750e6819a6fcebef10579ba995096959"
-    , "564e1c9fbcb12878df2bd49202cbf821"
-    , ""
-    , "bf7de29e99e7f0e1b9f96f3b1902fb4049c8c6234d20de8316ebe66d97725457"
-    , "8b7326621f6afbd44a726de48d03bcc5331f7306026c229ea9523497fbeaa88d"
-    , "33b00b31623d6160c4c6740363a96481be14b19bc47be95641227284c366922a"
-    , "2d812c8203575790ad6b6f2ed91a49d57460de779a3e881bef3be12e8766dc91"
-    , "5574e0b4efc17e8ce136e592beabfe32551072bddd740929e698467b40b3991f028a22c760f7034853cc53007e3793e3c4a600d9e9d94528f8dc09aeba86146cdde2b7f71255ae0efc529b49be2205979dba6525bfe155e8819e8e2aeeaa285704242da90b4c4535101cc47d94b0e388a1b2e63ad0cbe158b9e1bbae9cc0007c"
-    ],
-    -- COUNT = 5
-    [ "61f1471ced56aa04c57e1b512307d4cb92497d9592d7e9e35356e99d585cab1b"
-    , "84714e960c403a4fac06b2828cc564d9"
-    , ""
-    , "7bf97db3c102edc81596d4757045fe6bdc008f35792fc6290b77d889c09c33a8"
-    , "5b8bdc41f76d98cfa71ed976ea3994706375c8841adb8b6b3b6418e3132e8832"
-    , "94c8a8fdf38a6ccb8571c89420d899adab169214bb0dfcd43a04622e289935b2"
-    , "8a4b46e0a7a55907365f82d4ab9376509bd44728cab8cbafb0da901012ad8dcd"
-    , "933eb159a6af7455b60e40586c064f05f1970f564281b1ebc4662701ac1f299e4eb908c4afcb2e065191281ab576f684aefedd6904bad04d96bd93c0516c62a496c3073a0cda0676a11cc08866b0cc74f62cb9d3db48673b2c3fbeada69f922b4b795ccba22df12ef7125909381f7d681f6b9caba02fb913c5437b98c040c576"
-    ],
-    -- COUNT = 6
-    [ "a1d5bb7d70621dee6b668b28c56d5610c2f8ced30284cc3e0e48de331af05062"
-    , "88a49e3e54c5ea54c98b95de81bcc807"
-    , ""
-    , "b4e2426e98f6eed97a6cdf690a89ee109e84c3dca16c883c26fa4ac671638d8d"
-    , "5bd1e086ed228cfd8b55c1731fea40c3a63d022599ca2da4bb23118f4821ba62"
-    , "b754b53ac226e8ebe47a3d31496ec822de06fca2e7ef5bf1dec6c83d05368ec3"
-    , "fa7e76b2805d90b3d89fff545010d84f67aa3a2c9eb2ba232e75f4d53267dac3"
-    , "df6b2460688fa537df3ddfe5575fca5eb8abad56cbc4e5a618a2b4a7daf6e215c3a497974c502f9d0ec35de3fc2ea5d4f10de9b2aee66dcc7e7ae6357983095959b817f0383e3030771bd2ed97406acf78a1a4a5f30fa0992289c9202e69e3eb1eabe227c11409ff430f6dfca1a923a8b17bc4b87e908007f5e9759c41482b01"
-    ],
-    -- COUNT = 7
-    [ "68f21d14525d56233c7e263482d344c388a840103a77fb20ac60ce463cabdc79"
-    , "59fa80ae570f3e0c60ac7e2578cec3cb"
-    , ""
-    , "7584b4166530442f06e241dd904f562167e2fdae3247ab853a4a9d4884a5fa46"
-    , "f6a5482f139045c5389c9246d772c782c4ebf79c3a84b5cf779f458a69a52914"
-    , "9d37b1ce99f8079993ddf0bd54bab218016685b22655a678ce4300105f3a45b7"
-    , "4c97c67026ff43c2ee730e7b2ce8cce4794fd0588deb16185fa6792ddd0d46de"
-    , "e5f8874be0a8345aabf2f829a7c06bb40e60869508c2bdef071d73692c0265f6a5bf9ca6cf47d75cbd9df88b9cb236cdfce37d2fd4913f177dbd41887dae116edfbdad4fd6e4c1a51aad9f9d6afe7fcafced45a4913d742a7ec00fd6170d63a68f986d8c2357765e4d38835d3fea301afab43a50bd9edd2dec6a979732b25292"
-    ],
-    -- COUNT = 8
-    [ "7988146cbf9598d74cf88dc314af6b25c3f7de96ae9892fb0756318cea01987e"
-    , "280bc1ae9bfdf8a73c2df07b82a32c9c"
-    , ""
-    , "2bbc607085232e5e12ccf7c0c19a5dc80e45eb4b3d4a147fe941fa6c13333474"
-    , "f3f5c1bb5da59252861753c4980c23f72be1732f899fdea7183b5c024c858a12"
-    , "44d0cfc4f56ab38fa465a659151b3461b65b2462d1ad6b3463b5cf96ad9dc577"
-    , "34fb9a3cdacc834ff6241474c4f6e73ed6f5d9ea0337ab2b7468f01ad8a26e93"
-    , "4caec9e760c4d468e47613fe50de4a366ae20ba76793744a4e14433ea4de79dc188601eb86c803b094641ab2337b99d459d37decc7d27473057be45ba848868ee0fb5f1cf303d2fcd0b3e0c36f65a65f81b3fee8778a1f22302e25dfe34e6d587fa8864e621121880f7cd55f350531c4ce0530099eec2d0059706dcd657708d9"
-    ],
-    -- COUNT = 9
-    [ "1c974c953fa2a057c9fc9409a6843f6f839aa544bca4fa11e48afd77931d4656"
-    , "ed7c08285464af7a5dbdc10b944a1270"
-    , ""
-    , "78146ad135acb836360d36afc50653dcc36c21662da2a6f6ae05222e75f34000"
-    , "263c4984c238ded333c86472866353817379502157172cfa51371d82b1efd7b5"
-    , "79b591529f9a26a0d7c8f8fd64e354b0c134ef1f757e43f9463b3dbb7a3da1ab"
-    , "7d8f7204b0b5401ddce9e88dcf5facb9a44660a9f5f1c862748e7269c29f7964"
-    , "72e2ca257b9edaf59b50e05a144f56fb517832fb9ad3489b1e664e3d5412cbf6b2883e891703b2e73aff9ab56da1009fcdef010ab4cdab996795c8f7c47fb1192bb160353997ad39d7d5fd0e2efc9103a7c3f158246afd53fe53ca6782f809698ef5f1f0d85536780a3fd6a8bafa475891c09213088bd1a3dc169257c34a517a"
-    ],
-    -- COUNT = 10
-    [ "56216d71984a77154569122c777ce57e1d101a6025b28163a25971d39c1c5d0f"
-    , "5cd148ba7e54f4975ac8e3e0f9b5d06a"
-    , ""
-    , "3580f8ca974626c77259c6e37383cb8150b4d0ab0b30e377bed0dc9d1ff1a1bf"
-    , "15633e3a62b21594d49d3d26c4c3509f96011d4dbb9d48bbbea1b61c453f6abe"
-    , "6068eaca85c14165b101bb3e8c387c41d3f298918c7f3da2a28786ab0738a6fc"
-    , "e34f92d2b6aeeeea4ff49bfe7e4b1f462eabb853f0e86fbae0e8b3d51409ce49"
-    , "587fdb856abc19ede9078797ecb44099e07aadcd83acdcb2b090601d653f4a14c68ab2ebdda63578c5633a825bae4c0c818f89aac58d30fd7b0b5d459a0f3d86fcad78f4bb14dfff08ad81e4ea9f487cb426e91d6e80dfed436ba38fce8d6f21ca2151c92dd5c323b077d6139c66395558f0537026c4a028affa271ef4e7ea23"
-    ],
-    -- COUNT = 11
-    [ "83eb48bedc1e9294866ab8e5322ef83f6f271f8188e8fdabe5817788bd31570d"
-    , "d6ed90bc692237f132441ede857a6629"
-    , ""
-    , "a4e5e127f992bd5ca79ee56bb8a9bccf74c21814bfaf97ffd052211e802e12e4"
-    , "84136e403d9ed7f4515c188213abcfaca35715fa55de6d734aec63c4606a68f1"
-    , "fe9d8ef26e2d2e94b99943148392b2b33a581b4b97a8d7a0ecd41660a61dd10b"
-    , "594dad642183ce2cdc9494d6bcb358e0e7b767c5a0fa33e456971b8754a9abd5"
-    , "86715d43ba95fbbca9b7193ea977a820f4b61ba1b7e3b8d161b6c51b09dfd5040d94c04338b14d97ed25af577186b36ae7251a486c8a2d24a35e84a95c89d669d49e307b4a368b72164135ac54d020a970a180dfbed135d2c86f01270846d5301bd73db2c431a8aa10a0a3d03d146e5fafb9a2aa0b4efc80edab06ff3b532236"
-    ],
-    -- COUNT = 12
-    [ "ba2c94203dab2e6499d8c50dca7b5c34a6b4764834f9816631aa21b9f9c37361"
-    , "67db133bdefb25e395085bceee5a0afc"
-    , ""
-    , "fa8984d16d35302cda35a3a355ab9242ec96fec0652d39282d4a0abf0a80df87"
-    , "b6fed10255a3fea6772ae1ae6d9f6cbb9bfaa34804e58a5b786f9bc60b348ccd"
-    , "445e072244edc716d3528f0e0a20ff0cd8f819c0d031736c8da122748f24d6c6"
-    , "1f856e403c4fa035bac9aa81a20e347c7d8b213aab699d69d9d6186a06ac45c1"
-    , "79f33fc36b3b47d9ac805bdbbe699909a8d0beb689a8b2723c291bd5bf7f3ce61343d4722a14e4add36312dbb0594910c8828aff1abc159915d498106f9ffb31147478d8c9ef75d1536ba5036506b313f6e85033f8f6fea2a4de817c867a59378c53c70a2f108275daedd415c05b61c4fd5d48c54be9adb9dea6c40a2ec99ee0"
-    ],
-    -- COUNT = 13
-    [ "0db4c51492db4fe973b4bb1c52a1e873b58fc6bb37a3a4bfc252b03b994495d1"
-    , "a2a3900f169bba3f78a42526c700de62"
-    , ""
-    , "29d5aab356876447e3a20d81c7e3fc6975e2b984180a91493044442999e1ca3a"
-    , "40b34183b4e72cdff5952b317b3d45943d0fdcfa0527f3563055f7c73ae8f892"
-    , "dc94220c99ffb595c7c4d6de8de5a6bb4b38847169e24a557ef6d879ad84149d"
-    , "b2376626fd2f5218b3ed4a5609b43aa24d371cd2176ea017c2b99cf868060021"
-    , "f0bd6bc4c506d9427a09352d9c1970b146360732841a6323f4cb602c87dedfb5ff7e6964b9144933af3c5c83017ccd6a94bdca467a504564aaa7b452591a16ff6a1e7e94ddc98f9a58016cdcb8caaed6c80671ba48cc81a832d341093dda1d4e5001ec6bf66348b21e3692a13df92538ad572bb2023822072fc95f9590293ffc"
-    ],
-    --  COUNT = 14
-    [ "593845f0adfeffa7c169f8a610147ae8a08c0072fc0c14c3977d3de0d00b55af"
-    , "9e0eb2507342ee01c02beadee7d077bd"
-    , ""
-    , "aefe591697eab678c52e20013aa424b95cfd217b259757fbe17335563f5b5706"
-    , "cbb5be0ef9bf0555ee58955c4d971fb9baa6d6070c3f7244a4eb88b48f0793bf"
-    , "6dd878394abdc0402146ba07005327c55f4d821bfebca08d04e66824e3760ab4"
-    , "ba86a691d6cbf452b1e2fd1dfb5d31ef9ea5b8be92c4988dc5f560733b371f69"
-    , "00735cbfafac5df82e5cb28fc619b01e2ba9571dc0023d26f09c37fb37d0e809066165a97e532bf86fa7d148078e865fe1a09e27a6889be1533b459cd9cd229494b5cf4d2abf28c38180278d47281f13820276ec85effb8d45284eb9eef5d179ab4880023ab2bd08ee3f766f990286bf32430c042f5521bbfd0c7ee09e2254d7"
-    ]
-    ]
-
-{-
-    [SHA-256]
-    [PredictionResistance = False]
-    [EntropyInputLen = 256]
-    [NonceLen = 128]
-    [PersonalizationStringLen = 256]
-    [AdditionalInputLen = 0]
-    [ReturnedBitsLen = 1024]
--}
-
-r3 :: [TestVector]
-r3 =
-    [
-    -- COUNT = 0
-    [ "fa0ee1fe39c7c390aa94159d0de97564342b591777f3e5f6a4ba2aea342ec840"
-    , "dd0820655cb2ffdb0da9e9310a67c9e5"
-    , "f2e58fe60a3afc59dad37595415ffd318ccf69d67780f6fa0797dc9aa43e144c"
-    , "e0629b6d7975ddfa96a399648740e60f1f9557dc58b3d7415f9ba9d4dbb501f6"
-    , ""
-    , ""
-    , ""
-    , "f92d4cf99a535b20222a52a68db04c5af6f5ffc7b66a473a37a256bd8d298f9b4aa4af7e8d181e02367903f93bdb744c6c2f3f3472626b40ce9bd6a70e7b8f93992a16a76fab6b5f162568e08ee6c3e804aefd952ddd3acb791c50f2ad69e9a04028a06a9c01d3a62aca2aaf6efe69ed97a016213a2dd642b4886764072d9cbe"
-    ],
-    -- COUNT = 1
-    [ "cff72f345115376a57f4db8a5c9f64053e7379171a5a1e81e82aad3448d17d44"
-    , "d1e971ec795d098b3dae14ffcbeecfd9"
-    , "6ec0c798c240f22740cad7e27b41f5e42dccaf66def3b7f341c4d827294f83c9"
-    , "45ec80f0c00cad0ff0b7616d2a930af3f5cf23cd61be7fbf7c65be0031e93e38"
-    , ""
-    , ""
-    , ""
-    , "17a7901e2550de088f472518d377cc4cc6979f4a64f4975c74344215e4807a1234eefef99f64cb8abc3fb86209f6fc7ddd03e94f83746c5abe5360cdde4f2525ccf7167e6f0befae05b38fd6089a2ab83719874ce8f670480d5f3ed9bf40538a15aaad112db1618a58b10687b68875f00f139a72bdf043f736e4a320c06efd2c"
-    ],
-    -- COUNT = 2
-    [ "b7099b06fc7a8a74c58219729db6b0f780d7b4fa307bc3d3f9f22bfb763596a3"
-    , "b8772059a135a6b61da72f375411de26"
-    , "2ac1bfb24e0b8c6ac2803e89261822b7f72a0320df2b199171b79bcbdb40b719"
-    , "9aec4f56ec5e96fbd96048b9a63ac8d047aedbbeea7712e241133b1a357ecfc4"
-    , ""
-    , ""
-    , ""
-    , "0e1f2bfef778f5e5be671ecb4971624ec784ed2732abc4fbb98a8b482fb68737df91fd15acfad2951403ac77c5ca3edffc1e03398ae6cf6ac24a91678db5c7290abc3fa001aa02d50399326f85d2b8942199a1575f6746364740a5910552c639804d7530c0d41339345a58ff0080eccf1711895192a3817a8dc3f00f28cc10cc"
-    ],
-    -- COUNT = 3
-    [ "7ba02a734c8744b15ef8b4074fe639b32e4431762ab5b7cd4d5df675ea90672b"
-    , "8a424f32108607c8f1f45d97f500ee12"
-    , "3ad627433f465187c48141e30c2678106091e7a680229a534b851b8d46feb957"
-    , "d8f02b59b6a3dd276bc69cba68efcf11ab83ead1397afd9841786bd1bb5da97a"
-    , ""
-    , ""
-    , ""
-    , "1fb91186ba4b4459d994b4b9f4ca252c7be6294d6cdb5fe56f8ff784d4b190a1c6456e0a41223bbbdf83ed8e7cfbfa765d9d8bc7ea5f4d79ea7eccb4928081a21de4cca36620d6267f55d9a352b76fc0a57375884112c31f65ff28e76d315698c29e6c4c05cb58b0a07ae66143b4abc78b9d25c78b4121e1e45bef1a6c1793e2"
-    ],
-    -- COUNT = 4
-    [ "9a8865dfe053ae77cb6a9365b88f34eec17ea5cbfb0b1f04d1459e7fa9c4f3cb"
-    , "180c0a74da3ec464df11fac172d1c632"
-    , "336372ec82d0d68befad83691966ef6ffc65105388eb2d6eed826c2285037c77"
-    , "75b95108eff1fabe83613e1c4de575e72a5cdc4bb9311dd006f971a052386692"
-    , ""
-    , ""
-    , ""
-    , "3c683f6d4f8f5a4018d01633dfee74266aaa68ed6fc649e81b64dfdf5f75e75d5c058d66cf5fd01a4f143a6ff695517a4a43bd3adfd1fb2c28ba9a41063140bedbffdb4d21b1ace1550d59209ec61f1e2dbacb2a9116a79cb1410bf2deca5218080aacd9c68e1d6557721a8913e23f617e30f2e594f61267d5ed81464ee730b2"
-    ],
-    -- COUNT = 5
-    [ "22c1af2f2a4c885f06988567da9fc90f34f80f6dd5101c281beef497a6a1b2f8"
-    , "3fafdecf79a4174801f133131629037b"
-    , "80327dac486111b8a8b2c8e8381fb2d713a67695c2e660b2b0d4af696cc3e1de"
-    , "f95a0e4bd24f0e2e9e444f511b7632868ead0d5bb3846771264e03f8ab8ed074"
-    , ""
-    , ""
-    , ""
-    , "77a7fea2f35a188f6d1bfdd49b569d8c45e2dd431d35a18c6f432c724f1e33ae92cb89a9cf91519e50705a53199f5b572dc85c1aef8f28fb52dc7986228f66954d54eda84a86962cf25cf765bd9949876349291b1aae5f88fcf4b376912d205add4f53b2770c657946c0d824281f441509153f48356d9d43f8a927e0693db8fc"
-    ],
-    -- COUNT = 6
-    [ "d0840e3a8d629d5b883d33e053a341b21c674e67e1999f068c497ecfaabfd6f6"
-    , "071de7244ecb2fdf7ab27f2d84aa7b7a"
-    , "90d609527fad96ffe64ab153860346f3d237c8940555ae17b47842d82d3b0943"
-    , "1dd1a8b59856c49a388f594c5f42cc2e4a56b3ccb8a65e7066e44c12f4344d50"
-    , ""
-    , ""
-    , ""
-    , "7ab28a9b2d3ae999195553e6550cced4c2daccbe7ec9dcbb0d467fabba185b727fbfd9830242cd098f4db3cf4a85e8bf8e8d5974b62b28550922b32ed5bfc1a522b6605cf93bf8d90bdec1c5b9e59c6fc37a817d437068a87254be1f7c4618ada46fbc3a2efb02e44524e21d91be7534cf05fbfd858304b706d6a91ea1cc6ad5"
-    ],
-    -- COUNT = 7
-    [ "2e2dd56869104492767a59778652831919e1c8b970f84e824ae4116597a0ab7f"
-    , "01c42a7e983641de46c82fd09b4f2f76"
-    , "bcd9e1508fcc22820a8be07180fea5045367333b569e111b011cd57dc1858765"
-    , "7306507cd3ca7eec667e640d270cfbb033063d97520b6b7e38ff3cea0e79d12b"
-    , ""
-    , ""
-    , ""
-    , "b915726c7b8c5dc3975f1a334684b973abf6a9495d930088cf5d071548e4fd29a67b55cc561ed6949ad28150a9fb4307c1fa5f783a7ea872e8d7c7e67ff0c2906081ee915737d813c25be5c30b952a36f393e6baa56ab01adc2b4776ad7b5d036a53659877c7a4e5220a897d6c0799af37beeed91173fbe9c613c3b6b9bb28e5"
-    ],
-    -- COUNT = 8
-    [ "d1aab0f16bd47a5ccd67c22e094daa3735eae21aa57f0bcd9e053d9d0d545cb8"
-    , "199310dfe1b01265b8c0d2b46d6c7c9f"
-    , "625b4b8f4de72ea9cb6f70556322dc2a19d6b2b32de623f557e419a084ba60fd"
-    , "f50cabae4e060f3971096b78e550cda2837a26a693d905db2d992d589b268f44"
-    , ""
-    , ""
-    , ""
-    , "987e1fdfe004c619cf1e9034576707eccd849400e19c87a1fef5b0179ec51c42a2f8c45d7942d0023a023c89f188b2634362703985695369863322f58619c50a7385a2dc91fc78f94b59f0131dc2b56a0d7c699d427285da1c104b0ad1739da10d8071c23993787045dc21f0070e1e9aa1658fc8e3add73dac7262e80e0aa2ee"
-    ],
-    -- COUNT = 9
-    [ "449480eaa100aff6f48dc6286a5a81b9728b084864f78a9da98f606a00a6a41f"
-    , "e53c6c5ac3da9f4726389a03f97bb640"
-    , "6b8fedc084d8e28d333aef6db3702b6351f0d24e30908cccb63794282655886b"
-    , "73a6d64e1966ae324388dc12c14544e9dc5ae4fcb331e99d350c456ff16f9aa0"
-    , ""
-    , ""
-    , ""
-    , "a06912d362da7eb25598857f6d65344c3e23ec3deb80c6e43158845b95eaeca241c0bbbd67ac385e24693444455cc1c2c08c1134d956b8bc93b28be9c2d3322b3e09252979dfb8d39d04c94f81bebda5c73110605a237b561216bda9ee9bdee1cc0c7728bcc8304682334ca944e467a27a85313fa5395a9c790e35defd2edb12"
-    ],
-    -- COUNT = 10
-    [ "9a6174166e97aa4981ddf580bc01c96754b9f0ba042750aabfda1cffe56e8581"
-    , "d7512ff6b7db7ce141b2bb01dcd0425e"
-    , "ed75288f23275f9422444da5d3b53ccb3c4ac8acfb659a1e9b7655c2db52f879"
-    , "6888b9277e57dc57663d402eba8d03cf56a070dc868e6a128b18040002baf690"
-    , ""
-    , ""
-    , ""
-    , "03519dfb2ff88cc2b53eecc48ae2a18ddcf91a5d69d5aefcdda8444e6df790a5240e67b2a4de75b4bb8a31f0f8aeb5e785ffb7a1341bb52fe00a05ee66fa2d44ea9956e055f9ffa6647c3bfe851ab364ade71a0d356de710ddafb7622b1da1bc53fd4d3210407289c68d8aeb346bf15806dbe787e781b94f63da3e1f61b5ac60"
-    ],
-    -- COUNT = 11
-    [ "9c6ae1002ee1b0add0be563ce50f899da936e13efa620d08c2688c192514763a"
-    , "fde7db5160c73044be73e9d4c1b22d86"
-    , "8fdaaeffd64e53f7b4374d902d441209964e12b65d29afec258e65db6de167ca"
-    , "bcc28fd58e397f53f494ad8132df82c5d8c4c22ea0b7139bd81eeba65667bb69"
-    , ""
-    , ""
-    , ""
-    , "021d938c9b4db780c7d8134aeff1053e5b8843370b8ae9a6749fca7199d809810f1bc8dfa49426470c30c3616f903e35fbacb23420a32f1bee567cc32300f704246ddc0217f236ef52c3ec9e2433ca66f05c25721f7661c43f22c1a125ed5db531bd0836eb435c27eefc7424ce9d845e1d4cc4c503097b4ffca788e674a5cb53"
-    ],
-    -- COUNT = 12
-    [ "fe96a85b69d46b540918927bb609dc57642eeaefd46bb5da2163a0bc60294b58"
-    , "22195a410d24db45589448dfe979d3fd"
-    , "20f698833a4472fd7b78fb9b0c4eb68604f166a2694c4af48dac2b2376790e1e"
-    , "09cb870879d3f734214f6a4bd2e08c62a2a954bebe559416d8c3551aafe71d6a"
-    , ""
-    , ""
-    , ""
-    , "d3e96dbe29e1fcb8ed83b19dbfb240e6f41679fbe83853aa71446617e63e5af78cf98b331d15bccb8c673c4e5d5dcec467a1fe26a6cd1696d0c9bc49f78139d051287df7f3ae0dbb4bbf581cb8211931063c3f4612ced53f59d1b4ebb875729139f5d2a7d60642e8f2835eed888b7e3e49c0dffd012cd746abfa3e1c5c2308c6"
-    ],
-    -- COUNT = 13
-    [ "a4fd693ff0a8af24bcec352d3196549fd0da5ee5d99ca58416ca03ce4c50f38e"
-    , "8cd67f2bf71d4366ce61396642531ff5"
-    , "368969c15a4849d7593be8b162113b9298a535c148ff668a9e8b147fb3af4eba"
-    , "83d2be9a0d74e6a42159ae630acebf4e15271ef7f14f3de14752be0e0e822b11"
-    , ""
-    , ""
-    , ""
-    , "e9188fc0eaec74b2608e21e3a40be94aaf4ae08eb684de8f8bba2d5fd3b073aa5531c938c0fc628da65725c54b5c68bb91d7d326565e96685e0a4e7b220c50e0caf1628edba5bd755b31894f8cb90afa76e88c5eb9e61b4932444c1397dee3e32241a3fb70a3929e49f6da02eea54812abb3d6b5cee18f03af1e0b4958430ab3"
-    ],
-    -- COUNT = 14
-    [ "254ff5687a6dad3f1d237dc762f58d24ef2e2c084d0a48d26a3dc81e5490cda3"
-    , "f2ec392acca491e03ce47b95963a49fc"
-    , "f806b9b4a56682c61b55cb6a334caf87ffe135adfea6d0c3fc22b39898fbd078"
-    , "b8494b1c1f1752fb6f80d732a89b08115857f7cc96e7dff05ebb822706889917"
-    , ""
-    , ""
-    , ""
-    , "0e527e00494d55564f9d9b28e7110f9a61ce36c883b5be2dcb055444164cdddd1a9f2731716f22d6ff476ce413c77abfc0e946871d5481345c2e97b4bfdd12ac03df606fc56bdb99ac7b71a69b5b9160373bbec3e9dde477180af454e7acc6bc58dc0afb4281c0de4354c1bf599054e3800c6d60d892858865b5361f50bfca9b"
-    ]
-    ]
-
-{-
-    [SHA-256]
-    [PredictionResistance = False]
-    [EntropyInputLen = 256]
-    [NonceLen = 128]
-    [PersonalizationStringLen = 256]
-    [AdditionalInputLen = 256]
-    [ReturnedBitsLen = 1024]
--}
-
-r4 :: [TestVector]
-r4 =
-    [
-    -- COUNT = 0
-    [ "cdb0d9117cc6dbc9ef9dcb06a97579841d72dc18b2d46a1cb61e314012bdf416"
-    , "d0c0d01d156016d0eb6b7e9c7c3c8da8"
-    , "6f0fb9eab3f9ea7ab0a719bfa879bf0aaed683307fda0c6d73ce018b6e34faaa"
-    , "8ec6f7d5a8e2e88f43986f70b86e050d07c84b931bcf18e601c5a3eee3064c82"
-    , "1ab4ca9014fa98a55938316de8ba5a68c629b0741bdd058c4d70c91cda5099b3"
-    , "16e2d0721b58d839a122852abd3bf2c942a31c84d82fca74211871880d7162ff"
-    , "53686f042a7b087d5d2eca0d2a96de131f275ed7151189f7ca52deaa78b79fb2"
-    , "dda04a2ca7b8147af1548f5d086591ca4fd951a345ce52b3cd49d47e84aa31a183e31fbc42a1ff1d95afec7143c8008c97bc2a9c091df0a763848391f68cb4a366ad89857ac725a53b303ddea767be8dc5f605b1b95f6d24c9f06be65a973a089320b3cc42569dcfd4b92b62a993785b0301b3fc452445656fce22664827b88f"
-    ],
-    -- COUNT = 1
-    [ "3e42348bf76c0559cce9a44704308c85d9c205b676af0ac6ba377a5da12d3244"
-    , "9af783973c632a490f03dbb4b4852b1e"
-    , "2e51c7a8ac70adc37fc7e40d59a8e5bf8dfd8f7b027c77e6ec648bd0c41a78de"
-    , "45718ac567fd2660b91c8f5f1f8f186c58c6284b6968eadc9810b7beeca148a1"
-    , "63a107246a2070739aa4bed6746439d8c2ce678a54fc887c5aba29c502da7ba9"
-    , "e4576291b1cde51c5044fdc5375624cebf63333c58c7457ca7490da037a9556e"
-    , "b5a3fbd57784b15fd875e0b0c5e59ec5f089829fac51620aa998fff003534d6f"
-    , "c624d26087ffb8f39836c067ba37217f1977c47172d5dcb7d40193a1cfe20158b774558cbee8eb6f9c62d629e1bcf70a1439e46c5709ba4c94a006ba94994796e10660d6cb1e150a243f7ba5d35c8572fd96f43c08490131797e86d3ed8467b692f92f668631b1d32862c3dc43bfba686fe72fdd947db2792463e920522eb4bc"
-    ],
-    -- COUNT = 2
-    [ "b63fdd83c674699ba473faab9c358434771c5fa0348ca0faf7ebd7cf5891826b"
-    , "5fd204e2598d9626edab4158a8cfd95f"
-    , "2a5dfad8494306d9d4648a805c4602216a746ae3493492693a50a86d1ba05c64"
-    , "adea5ba92f8010bb1a6a4b6fae2caa0b384165adf721253afd635d6021f764af"
-    , "07c69d8d2b8aa1454c5c48083dd41477fda6bfcf0385638379933a60ed2e0a77"
-    , "a14e902247a3d6493d3fbc8519518b71a660e5502cf7ecfc796cfaa5b4ee4baa"
-    , "60e690e4a1eba14aec5187112a383e9991347fab7bac7cb2a40a52579a0d2718"
-    , "792b47b6ed221623bb187d63e3f039c6983d94efd5771dc9b4c40bee65924513485a6332baeda6a96f9bb431f592d73462b61d9d914a72b56fa9d87597426fb246424ebcd7abd51b2eefec8f5b839c0b3c34015342ace296b5f2218fa194b50aea1c89663460292c92c45f112ddbf6b9406f6e7ccee9c47ed2d90a27be5dd73e"
-    ],
-    -- COUNT = 3
-    [ "dab85f98eaf0cfba013b97de4d9c264ca6fe120366cb83e8b3113c68b34e39d5"
-    , "d05108e1028ae67b4ea63bdc6d75eb88"
-    , "09fed3822f6f5e5b9e575d31dc215de1607b0dfc927412618c2d8f79166dbaba"
-    , "1794885a64470744198b7d0bc24472ffe8daf3c7eb219df6ddf180e484fe0aa5"
-    , "8d74d01b582f70b92f53b43468084e1586d9b36465d333d5faaf6911e62fe40e"
-    , "ef7f6b6eb479ab05b3f9ab6dd72eac8b1e86d887f1bcae363cae386d0275a06f"
-    , "7442b2a792a6a29559bb8a515d56916ee18200580aa02e1237dd358619382d8f"
-    , "49d2cbfa0897b7d961c293c1e572fb26f28e7b956e746f6eda90454c1370a29e25303ceadc7837514dc638553b487ef9487c977c10625409178ad6506d103c487a66655d08659d92a4d5994d1c8ddb28fe60f2e49577d6e80cae1478068c98268f45e6293c9326c7f726ec89601351c0a26fd3a6549f8a41c6f58692c86594c0"
-    ],
-    -- COUNT = 4
-    [ "0f0aa84ef12e10ae2b279e799c683441862457b9bc25581c2cd3d5b58a5b3246"
-    , "f74f4230c2427a52f01f39e825d250ac"
-    , "d02b2f53da48b923c2921e0f75bd7e6139d7030aead5aeebe46c20b9ca47a38a"
-    , "5222b26e79f7c3b7066d581185b1a1f6376796f3d67f59d025dd2a7b1886d258"
-    , "d11512457bf3b92d1b1c0923989911f58f74e136b1436f00bad440dd1d6f1209"
-    , "54d9ea7d40b7255ef3d0ab16ea9fdf29b9a281920962b5c72d97b0e371b9d816"
-    , "601cef261da8864f1e30196c827143e4c363d3fa865b808e9450b13e251d47fa"
-    , "e9847cefea3b88062ea63f92dc9e96767ce9202a6e049c98dc1dcbc6d707687bd0e98ed2cc215780c454936292e44a7c6856d664581220b8c8ca1d413a2b81120380bfd0da5ff2bf737b602727709523745c2ced8daef6f47d1e93ef9bc141a135674cba23045e1f99aa78f8cead12eeffff20de2008878b1f806a2652db565a"
-    ],
-    -- COUNT = 5
-    [ "6a868ce39a3adcd189bd704348ba732936628f083de8208640dbd42731447d4e"
-    , "efdde4e22b376e5e7385e79024350699"
-    , "f7285cd5647ff0e2c71a9b54b57f04392641a4bde4a4024fa11c859fecaad713"
-    , "0174f7f456ac06c1d789facc071701f8b60e9accebced73a634a6ad0e1a697d4"
-    , "5463bb2241d10c970b68c3abc356c0fe5ef87439fc6457c5ee94be0a3fb89834"
-    , "3ab62cdbc638c1b2b50533d28f31b1758c3b8435fe24bb6d4740005a73e54ce6"
-    , "2dbf4c9123e97177969139f5d06466c272f60d067fefadf326ccc47971115469"
-    , "8afce49dccc4ff64c65a83d8c0638bd8e3b7c13c52c3c59d110a8198753e96da512c7e03aeed30918706f3ad3b819e6571cfa87369c179fb9c9bbc88110baa490032a9d41f9931434e80c40ae0051400b7498810d769fb42dddbc7aa19bdf79603172efe9c0f5d1a65372b463a31178cbae581fa287f39c4fbf8434051b7419f"
-    ],
-    -- COUNT = 6
-    [ "bb6b339eae26072487084ec9e4b53f2f1d4267d205042e74c77fb9ca0591ba50"
-    , "c0e7bf6eb07feccbc494af4098e59d30"
-    , "34aeec7ed0cae83701b6477709c8654a1114212401dc91cbe7de39d71f0c06e1"
-    , "f47fc60afbeb807236f7974d837335bc0b22288ef09ddfcb684e16b4c36a050b"
-    , "e8071ccd84ac4527e5c6e85b0709ed867776f25ae0e04180dcb7105ecd3e3490"
-    , "fbac45b5952200ad7c4232500f2417a1c14723bdd1cc078821bc2fe138b86597"
-    , "c4292d7dbef3ba7c18bf46bcf26776add22ab8ee206d6c722665dec6576b1bc0"
-    , "228aa2a314fcbfe63089ce953ac457093deaa39dd9ce2a4ece56a6028a476a98129be516d6979eff5587c032cdf4739d7ac712970f600fa781a8e542e399661183e34e4b90c59ec5dc5cad86f91083529d41c77b8f36c5a8e28ba1a548223a02eaed8426f6fe9f349ebec11bc743e767482e3472ec2799c1f530ebdc6c03bc4b"
-    ],
-    -- COUNT = 7
-    [ "be658e56f80436039e2a9c0a62952dd7d70842244b5ab10f3b8a87d36104e629"
-    , "33c9627455dfde91865aee93e5071147"
-    , "d3a6eb29b180b791984deb056d72c0608a2c9044237aecf100ccb03700064c5e"
-    , "bef24dc9a5aa23003d3825f9b2b00e7dab571ea6ad86415dbd30c0bbdce7b972"
-    , "047c29e4d1584fa70cb66e2aa148a2aa29837c5eee64dcac60fdba356cdf90bb"
-    , "41c4792161b1b00d410cb79cd56bd311a714fb78dc3471c25bdd7479f2e9a952"
-    , "cd4936d7bc3ea0e7201bcbefbc908215a97680ca6ce8672360aea600b6564308"
-    , "2c25557f6db07db057f56ad5b6dc0427d1a0e825c48c19a526f9a65087c6d1ead7c78363a61616c84f1022653af65173a3f9ec3275f2b0a0d0bc750194673c0eaa6c623cd88abb0c8979baee4cd85bfce2e4a20bfebf2c3be61676563767dfe229e0b7be67ad6fcd116dd0b460708b1b0e5c3d60f3dd8138030404d197375d75"
-    ],
-    -- COUNT = 8
-    [ "ae537f31a28ca14500e759716bc207983bfeab60b25079fa30b77b8d41244cb9"
-    , "fca9e27d8ab84cf9b9ce491ec5d8cb67"
-    , "8c9cb2b19aa3abe83c8fe7da96e9c11648252653a29dcd5bf0ac334ac587f032"
-    , "1eb52777be480f05115ae6370f30159a94d50ffcc64454678ab1d1ac6f166fa7"
-    , "9cdf6f1a2bc07acd4b0f43b5f2b892a1153e2669f237d257923636094fb40b54"
-    , "692d512722de6ba720fd23c8994ac63179b5f7e611addf9cfacd60e06e144a6a"
-    , "bbeea7b2bea821f339f494947c0b4bae8056119db69a3cbef21914953729cdef"
-    , "c0c4fb7080c0fbe425c1b756fb3a090cb0d08c7027d1bb82ed3b07613e2a757f83a78d42f9d8653954b489f800a5e058ebc4f5a1747526541d8448cb72e2232db20569dc96342c36672c4be625b363b4587f44557e58cedb4597cb57d006fda27e027818ae89e15b4c6382b9e7a4453290ea43163b4f9cae38b1023de6a47f7b"
-    ],
-    -- COUNT = 9
-    [ "2f8994c949e08862db0204008f55d3561f3e0362df13b9d9a70fda39938f2d33"
-    , "1bf3e94ea858160b832fe85d301256f5"
-    , "b46671cf7fa142e7012ed261e1fe86714711c246c7d1c0330fa692141e86d5d1"
-    , "5ecdb1e8fe12260b9bfe12d6e6f161474fa2311e12e39b0beb0fcd92a6737b73"
-    , "3ce9a29f0207d079e6dc81fb830356e555f96a23ea71424972ea9308965786d3"
-    , "db950000c0776cc0e049929ce021020adc42d29cd9b5d8f7117fbe6bde3e594f"
-    , "fc18ee6dd3dac2306774f0ac36cd789e33462d72a8c75df9057123db33e5f7bc"
-    , "8546362cc8af9b78dd6e8eb2c37db96e70708852bfd9380abedc7f324575a167bea18f632f3e19d099cfbf310773f9719eec036d2e09f393a023add8ebdc4fb87af43b2fe6c7eaa4d39f8022ce247aa45fdc84d1b92cacce6eae8252a03ec2ec5330c01f56d113fd2ec3d0240af0afcf13ddde205bb5e7c2d912dcb4aee5dcf3"
-    ],
-    -- COUNT = 10
-    [ "0c85e31487de1d7ba4a7b998ac56dc42c6dc0eae7bf5c8aaf1e4e78875f5fb47"
-    , "de878f728f73f83dc2a2f550b96c8b97"
-    , "9aac37bce1a6a81dc7934e23747991e3cf48c55ffe5a57781c41768a35220a01"
-    , "2d5ca8af1a70cfdccd015ee3bf0665dd1941fc6a7317b9d0d06658f5744cfbd9"
-    , "db881e6d0dc3b62793d7da5fe5a18e33be9b93f4a63a00a878dfbecf0d383bd2"
-    , "f743ce1b72f3de4c901369eed581c626ed3081ca707e6634fdaff46721ce0878"
-    , "cd52da3ec8a839c537dacdea8506a3eeee879de388ff5e513322d6d1bb3ff694"
-    , "a5bdd57cb8fde6298e7c5e563afcca60dd472eca484bd8c3cc17f3307be09b601744dd3ab9e8a44107c5868824575f850c0f399b280cf198006f83ede8c0b537e9be227fa140b65995ad9dfa1f2303d560c3b7f59bedd93c1282ea263924469411c2653f87fd814c74cb91c148430481d64bad0fec3cbb3dd1f39aa55c36f81b"
-    ],
-    -- COUNT = 11
-    [ "93161b2dc08cb0fd50171141c865a841ca935cfdd2b5907d6ff8ab0348c4ceb0"
-    , "5cb9f6e5912b90c3349a50ab881b35a1"
-    , "0dceb4a36326c4df1685df43fddeecb5d0c76f00eb44826694f27e610290f6e1"
-    , "d8e9be44b5f293482548d4787762ebfb03c73c40e45385e8b98907cd66f493dd"
-    , "105a8f85d6959f3e043ef508cfea21d52123f03b7aea8034c4eec761eaba1fee"
-    , "bf781f7e489d9b4b5aa5ee6d1796468af672a8d25f311edf3c4b4dbf433d703f"
-    , "c81d6bcf1e5bf37e39dda1735c6f193df115b1a854a12e7cafe060afe4589335"
-    , "4306628124d0100fade7eaaf5edf227d50771f9e5f2e1e983800eef9a39fde0b0c280e63c8728d836b5b93ea794a32c1c04cfc54bd5300e3febb5fe2e1023eded8d7cd180279a598f76823e8d5a7dffcc93a09deec5d1f80838e938fba4de9f47e94b99382ae55f116df9c3b3ddf7e50516e203645852a415796f03a86418107"
-    ],
-    -- COUNT = 12
-    [ "1ae12a5e4e9a4a5bfa79da30a9e6c62ffc639572ef1254194d129a16eb53c716"
-    , "5399b3481fdf24d373222267790a0fec"
-    , "8280cfdcd7a575816e0199e115da0ea77cae9d30b49c891a6c225e9037ba67e2"
-    , "681554ff702658122e91ba017450cfdfc8e3f4911153f7bcc428403e9c7b9d68"
-    , "226732b7a457cf0ac0ef09fd4f81296573b49a68de5e7ac3070e148c95e8e323"
-    , "45942b5e9a1a128e85e12c34596374ddc85fd7502e5633c7390fc6e6f1e5ef56"
-    , "6fc59929b41e77072886aff45f737b449b105ed7eacbd74c7cbfedf533dbeaa1"
-    , "b7547332e1509663fcfea2128f7f3a3df484cd8df034b00199157d35d61e35f1a9d481c7d2e81305616d70fc371ee459b0b2267d627e928590edcac3231898b24ef378aa9c3d381619f665379be76c7c1bd535505c563db3725f034786e35bdd90429305fd71d7bf680e8cdd6d4c348d97078f5cf5e89dee2dc410fad4f2a30f"
-    ],
-    -- COUNT = 13
-    [ "29e20d724dfa459960df21c6ec76b1e6cabd23a9e9456d6c591d7e4529da0ef8"
-    , "95df1f837eba47a1687aa5c4ddcf8aaf"
-    , "3713b601e164b1a51dda1ca9242ff477514648e90d311a06e10ce5aa15da5d7f"
-    , "2a2a312626ca3e20034fc4f28033c7d573f66ef61ab2ea0c7bf0411a9d247264"
-    , "ec68be33ac8ff3dd127e051604898c0f9a501271859376653a0516336180993d"
-    , "9935499661d699a00c622a875441b4df5204958fe95892c8ce67f7dfb2be3e4a"
-    , "256a4ba9e8f439d5487fa5eb45efcf1bc1120491724db3abe328d951f2739fc9"
-    , "73114cb3624d687d4cd49a6e769dfc7a3f8901dc41f6ad1df4ce480536fa82e52ae958d0528640d92b8bb981b755058e32c4733682e5c4c0df41f3505a1643a0dd49cfdeaf7a18adffca88256c6d2cceb838af6c92a64bc21cb7a760a0391291bfe3575e014fc156323f8eb5e86518c669dad8d29ad5fd4ef6e296f4a0764c26"
-    ],
-    -- COUNT = 14
-    [ "1353f3543eb1134980e061fc4382394975dbc74f1f1ea5ecc02780a813ac5ee6"
-    , "cf584db2447afbe2c8fa0c15575ee391"
-    , "345b0cc016f2765a8c33fc24f1dcfa182cbe29d7eacbcdc9bcda988521458fc2"
-    , "ba60219332a67b95d90ec9de6b8453d4c8af991ae9277461ff3af1b92fc985d3"
-    , "6964b9b9842aec9c7ec2aad926d701f30eec76fe699265ae2a7765d716958069"
-    , "6a03c28a9365c558c33d3fdc7e5ebf0b4d32caac70df71403fd70ced09757528"
-    , "a58546c72a0b4d47c9bd6c19e7cf4ab73b2d7ba36c6c6dc08606f608795ebd29"
-    , "5b029ef68b6799868b04dc28dbea26bc2fa9fcc8c2b2795aafeed0127b7297fa19a4ef2ba60c42ff8259d5a759f92bd90fdfb27145e82d798bb3ab7fd60bfaefb7aefb116ca2a4fa8b01d96a03c47c8d987fdd33c460e560b138891278313bb619d0c3c6f9d7c5a37e88fce83e94943705c6ff68e00484e74ad4097b0c9e5f10"
-    ]
-    ]
-
diff --git a/tests/Network/Haskoin/Crypto/Keys/Tests.hs b/tests/Network/Haskoin/Crypto/Keys/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/Keys/Tests.hs
+++ /dev/null
@@ -1,142 +0,0 @@
-module Network.Haskoin.Crypto.Keys.Tests (tests) where
-
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.String (fromString)
-import Data.String.Conversions (cs)
-import qualified Data.ByteString as BS (length, index)
-import Data.Serialize (encode, runGet, runPut)
-
-import qualified Crypto.Secp256k1 as EC
-
-import Network.Haskoin.Test
-import Network.Haskoin.Crypto
-import Network.Haskoin.Util
-import Network.Haskoin.Internals (PubKeyI(..), PrvKeyI(..))
-
-tests :: [Test]
-tests =
-    [ testGroup "PubKey Binary"
-        [ testProperty "is public key canonical" isCanonicalPubKey
-        , testProperty "makeKey . toKey" makeToKey
-        , testProperty "makeKeyU . toKey" makeToKeyU
-        ]
-    , testGroup "Key formats"
-        [ testProperty "fromWif . toWif PrvKey" fromToWIF
-        , testProperty "constant 32-byte encoding PrvKey" binaryPrvKey
-        ]
-    , testGroup "Key compression"
-        [ testProperty "Compressed public key" testCompressed
-        , testProperty "Uncompressed public key" testUnCompressed
-        , testProperty "Compressed private key" testPrivateCompressed
-        , testProperty "Uncompressed private key" testPrivateUnCompressed
-        ]
-    , testGroup "From/To strings"
-        [ testProperty "Read/Show public key" testReadShowPubKey
-        , testProperty "Read/Show compressed public key" testReadShowPubKeyC
-        , testProperty "Read/Show uncompressed public key" testReadShowPubKeyU
-        , testProperty "Read/Show private key" testReadShowPrvKey
-        , testProperty "Read/Show private key" testReadShowPrvKeyC
-        , testProperty "Read/Show private key" testReadShowPrvKeyU
-        , testProperty "From string public key" testFromStringPubKey
-        , testProperty "From string compressed public key" testFromStringPubKeyC
-        , testProperty "From string uncompressed public key" testFromStringPubKeyU
-        , testProperty "From string private key" testFromStringPrvKey
-        , testProperty "From string compressed private key" testFromStringPrvKeyC
-        , testProperty "From string uncompressed private key" testFromStringPrvKeyU
-        ]
-    ]
-
--- github.com/bitcoin/bitcoin/blob/master/src/script.cpp
--- from function IsCanonicalPubKey
-isCanonicalPubKey :: ArbitraryPubKey -> Bool
-isCanonicalPubKey (ArbitraryPubKey _ p) = not $
-    -- Non-canonical public key: too short
-    (BS.length bs < 33) ||
-    -- Non-canonical public key: invalid length for uncompressed key
-    (BS.index bs 0 == 4 && BS.length bs /= 65) ||
-    -- Non-canonical public key: invalid length for compressed key
-    (BS.index bs 0 `elem` [2,3] && BS.length bs /= 33) ||
-    -- Non-canonical public key: compressed nor uncompressed
-    (not $ BS.index bs 0 `elem` [2,3,4])
-  where
-    bs = encode p
-
-makeToKey :: EC.SecKey -> Bool
-makeToKey i = prvKeySecKey (makePrvKey i) == i
-
-makeToKeyU :: EC.SecKey -> Bool
-makeToKeyU i = prvKeySecKey (makePrvKeyU i) == i
-
-{- Key formats -}
-
-fromToWIF :: ArbitraryPrvKey -> Bool
-fromToWIF (ArbitraryPrvKey pk) = (fromWif $ toWif pk) == Just pk
-
-binaryPrvKey :: ArbitraryPrvKey -> Bool
-binaryPrvKey (ArbitraryPrvKey k) =
-    (Right k == runGet (prvKeyGetMonad f) (runPut $ prvKeyPutMonad k)) &&
-    (Just k == decodePrvKey f (encodePrvKey k))
-  where
-    f = makePrvKeyG (prvKeyCompressed k)
-
-{- Key Compression -}
-
-testCompressed :: EC.SecKey -> Bool
-testCompressed n =
-    (pubKeyCompressed $ derivePubKey $ makePrvKey n) &&
-    (pubKeyCompressed $ derivePubKey $ makePrvKeyG True n)
-
-testUnCompressed :: EC.SecKey -> Bool
-testUnCompressed n =
-    (not $ pubKeyCompressed $ derivePubKey $ makePrvKeyG False n) &&
-    (not $ pubKeyCompressed $ derivePubKey $ makePrvKeyU n)
-
-testPrivateCompressed :: EC.SecKey -> Bool
-testPrivateCompressed n =
-    (prvKeyCompressed $ makePrvKey n) &&
-    (prvKeyCompressed $ makePrvKeyC n)
-
-testPrivateUnCompressed :: EC.SecKey -> Bool
-testPrivateUnCompressed n =
-    (not $ prvKeyCompressed $ makePrvKeyG False n) &&
-    (not $ prvKeyCompressed $ makePrvKeyU n)
-
-{- Strings -}
-
-testReadShowPubKey :: ArbitraryPubKey -> Bool
-testReadShowPubKey (ArbitraryPubKey _ k) = read (show k) == k
-
-testReadShowPubKeyC :: ArbitraryPubKeyC -> Bool
-testReadShowPubKeyC (ArbitraryPubKeyC _ k) = read (show k) == k
-
-testReadShowPubKeyU :: ArbitraryPubKeyU -> Bool
-testReadShowPubKeyU (ArbitraryPubKeyU _ k) = read (show k) == k
-
-testReadShowPrvKey :: ArbitraryPrvKey -> Bool
-testReadShowPrvKey (ArbitraryPrvKey k) = read (show k) == k
-
-testReadShowPrvKeyC :: ArbitraryPrvKeyC -> Bool
-testReadShowPrvKeyC (ArbitraryPrvKeyC k) = read (show k) == k
-
-testReadShowPrvKeyU :: ArbitraryPrvKeyU -> Bool
-testReadShowPrvKeyU (ArbitraryPrvKeyU k) = read (show k) == k
-
-testFromStringPubKey :: ArbitraryPubKey -> Bool
-testFromStringPubKey (ArbitraryPubKey _ k) = fromString (cs . encodeHex $ encode k) == k
-
-testFromStringPubKeyC :: ArbitraryPubKeyC -> Bool
-testFromStringPubKeyC (ArbitraryPubKeyC _ k) = fromString (cs . encodeHex $ encode k) == k
-
-testFromStringPubKeyU :: ArbitraryPubKeyU -> Bool
-testFromStringPubKeyU (ArbitraryPubKeyU _ k) = fromString (cs . encodeHex $ encode k) == k
-
-testFromStringPrvKey :: ArbitraryPrvKey -> Bool
-testFromStringPrvKey (ArbitraryPrvKey k) = fromString (cs $ toWif k) == k
-
-testFromStringPrvKeyC :: ArbitraryPrvKeyC -> Bool
-testFromStringPrvKeyC (ArbitraryPrvKeyC k) = fromString (cs $ toWif k) == k
-
-testFromStringPrvKeyU :: ArbitraryPrvKeyU -> Bool
-testFromStringPrvKeyU (ArbitraryPrvKeyU k) = fromString (cs $ toWif k) == k
diff --git a/tests/Network/Haskoin/Crypto/Mnemonic/Tests.hs b/tests/Network/Haskoin/Crypto/Mnemonic/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/Mnemonic/Tests.hs
+++ /dev/null
@@ -1,200 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Network.Haskoin.Crypto.Mnemonic.Tests (tests) where
-
-import Test.QuickCheck (Arbitrary, Property, arbitrary, choose, (==>))
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.Bits ((.&.), shiftR)
-import Data.Word (Word32, Word64)
-import qualified Data.ByteString as BS
-    ( ByteString
-    , empty
-    , append
-    , concat
-    , length
-    , last
-    )
-import qualified Data.ByteString.Char8 as C (words)
-import Data.Serialize (Serialize, encode)
-
-import Network.Haskoin.Test
-import Network.Haskoin.Crypto
-import Network.Haskoin.Util
-import Network.Haskoin.Internals (fromMnemonic, getBits)
-
-
-tests :: [Test]
-tests =
-    [ testGroup "Encode mnemonic"
-        [ testProperty "128-bit entropy -> 12 words" toMnemonic128
-        , testProperty "160-bit entropy -> 18 words" toMnemonic160
-        , testProperty "256-bit entropy -> 24 words" toMnemonic256
-        , testProperty "512-bit entropy -> 48 words" toMnemonic512
-        , testProperty "n-bit entropy -> m words" toMnemonicVar
-        ]
-    , testGroup "Encode/Decode Mnemonic"
-        [ testProperty "128-bit entropy" fromToMnemonic128
-        , testProperty "160-bit entropy" fromToMnemonic160
-        , testProperty "256-bit entropy" fromToMnemonic256
-        , testProperty "512-bit entropy" fromToMnemonic512
-        , testProperty "n-bit entropy" fromToMnemonicVar
-        ]
-    , testGroup "Mnemonic to seed"
-        [ testProperty "128-bit entropy" mnemonicToSeed128
-        , testProperty "160-bit entropy" mnemonicToSeed160
-        , testProperty "256-bit entropy" mnemonicToSeed256
-        , testProperty "512-bit entropy" mnemonicToSeed512
-        , testProperty "n-bit entropy" mnemonicToSeedVar
-        ]
-    , testGroup "Get bits from ByteString"
-        [ testProperty "Byte count" getBitsByteCount
-        , testProperty "End bits" getBitsEndBits
-        ]
-    ]
-
-binWordsToBS :: Serialize a => [a] -> BS.ByteString
-binWordsToBS = foldr f BS.empty
-  where
-    f b a = a `BS.append` encode b
-
-{- Encode mnemonic -}
-
-toMnemonic128 :: (Word64, Word64) -> Bool
-toMnemonic128 (a, b) = l == 12
-  where
-    bs = encode a `BS.append` encode b
-    l = length . C.words . fromRight $ toMnemonic bs
-
-toMnemonic160 :: (Word32, Word64, Word64) -> Bool
-toMnemonic160 (a, b, c) = l == 15
-  where
-    bs = BS.concat [encode a, encode b, encode c]
-    l = length . C.words . fromRight $ toMnemonic bs
-
-toMnemonic256 :: (Word64, Word64, Word64, Word64) -> Bool
-toMnemonic256 (a, b, c, d) = l == 24
-  where
-    bs = BS.concat [encode a, encode b, encode c, encode d]
-    l = length . C.words . fromRight $ toMnemonic bs
-
-toMnemonic512 ::
-    ((Word64, Word64, Word64, Word64), (Word64, Word64, Word64, Word64)) -> Bool
-toMnemonic512 ((a, b, c, d), (e, f, g, h)) = l == 48
-  where
-    bs = BS.concat
-        [ encode a, encode b, encode c, encode d
-        , encode e, encode f, encode g, encode h
-        ]
-    l = length . C.words . fromRight $ toMnemonic bs
-
-toMnemonicVar :: [Word32] -> Property
-toMnemonicVar ls = length ls <= 8 ==> l == wc
-  where
-    bs = binWordsToBS ls
-    bl = BS.length bs
-    cb = bl `div` 4
-    wc = (cb + bl * 8) `div` 11
-    l = length . C.words . fromRight $ toMnemonic bs
-
-{- Encode/Decode -}
-
-fromToMnemonic128 :: (Word64, Word64) -> Bool
-fromToMnemonic128 (a, b) = bs == bs'
-  where
-    bs = encode a `BS.append` encode b
-    bs' = fromRight (fromMnemonic =<< toMnemonic bs)
-
-fromToMnemonic160 :: (Word32, Word64, Word64) -> Bool
-fromToMnemonic160 (a, b, c) = bs == bs'
-  where
-    bs = BS.concat [encode a, encode b, encode c]
-    bs' = fromRight (fromMnemonic =<< toMnemonic bs)
-
-fromToMnemonic256 :: (Word64, Word64, Word64, Word64) -> Bool
-fromToMnemonic256 (a, b, c, d) = bs == bs'
-  where
-    bs = BS.concat [encode a, encode b, encode c, encode d]
-    bs' = fromRight (fromMnemonic =<< toMnemonic bs)
-
-fromToMnemonic512 ::
-    ((Word64, Word64, Word64, Word64), (Word64, Word64, Word64, Word64)) -> Bool
-fromToMnemonic512 ((a, b, c, d), (e, f, g, h)) = bs == bs'
-  where
-    bs = BS.concat
-        [ encode a, encode b, encode c, encode d
-        , encode e, encode f, encode g, encode h
-        ]
-    bs' = fromRight (fromMnemonic =<< toMnemonic bs)
-
-fromToMnemonicVar :: [Word32] -> Property
-fromToMnemonicVar ls = not (length ls > 8) ==> bs == bs'
-  where
-    bs = binWordsToBS ls
-    bs' = fromRight (fromMnemonic =<< toMnemonic bs)
-
-{- Mnemonic to seed -}
-
-mnemonicToSeed128 :: (Word64, Word64) -> Bool
-mnemonicToSeed128 (a, b) = l == 64
-  where
-    bs = encode a `BS.append` encode b
-    seed = fromRight (mnemonicToSeed "" =<< toMnemonic bs)
-    l = BS.length seed
-
-mnemonicToSeed160 :: (Word32, Word64, Word64) -> Bool
-mnemonicToSeed160 (a, b, c) = l == 64
-  where
-    bs = BS.concat [encode a, encode b, encode c]
-    seed = fromRight (mnemonicToSeed "" =<< toMnemonic bs)
-    l = BS.length seed
-
-mnemonicToSeed256 :: (Word64, Word64, Word64, Word64) -> Bool
-mnemonicToSeed256 (a, b, c, d) = l == 64
-  where
-    bs = BS.concat [encode a, encode b, encode c, encode d]
-    seed = fromRight (mnemonicToSeed "" =<< toMnemonic bs)
-    l = BS.length seed
-
-mnemonicToSeed512 ::
-    ((Word64, Word64, Word64, Word64), (Word64, Word64, Word64, Word64)) -> Bool
-mnemonicToSeed512 ((a, b, c, d), (e, f, g, h)) = l == 64
-  where
-    bs = BS.concat
-        [ encode a, encode b, encode c, encode d
-        , encode e, encode f, encode g, encode h
-        ]
-    seed = fromRight (mnemonicToSeed "" =<< toMnemonic bs)
-    l = BS.length seed
-
-mnemonicToSeedVar :: [Word32] -> Property
-mnemonicToSeedVar ls = not (length ls > 16) ==> l == 64
-  where
-    bs = binWordsToBS ls
-    seed = fromRight (mnemonicToSeed "" =<< toMnemonic bs)
-    l = BS.length seed
-
-{- Get bits from ByteString -}
-
-data ByteCountGen = ByteCountGen BS.ByteString Int deriving Show
-
-instance Arbitrary ByteCountGen where
-    arbitrary = do
-        ArbitraryByteString bs <- arbitrary
-        i <- choose (0, BS.length bs * 8)
-        return $ ByteCountGen bs i
-
-getBitsByteCount :: ByteCountGen -> Bool
-getBitsByteCount (ByteCountGen bs i) = BS.length bits == l
-  where
-    (q, r) = i `quotRem` 8
-    bits = getBits i bs
-    l = if r == 0 then q else q + 1
-
-getBitsEndBits :: ByteCountGen -> Bool
-getBitsEndBits (ByteCountGen bs i) = mask
-  where
-    r = i `mod` 8
-    bits = getBits i bs
-    mask = if r == 0 then True else BS.last bits .&. (0xff `shiftR` r) == 0x00
-
diff --git a/tests/Network/Haskoin/Crypto/Mnemonic/Units.hs b/tests/Network/Haskoin/Crypto/Mnemonic/Units.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/Mnemonic/Units.hs
+++ /dev/null
@@ -1,181 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Network.Haskoin.Crypto.Mnemonic.Units (tests) where
-
-import Test.HUnit (assertEqual)
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-
-import Data.Maybe (fromJust)
-import Data.String.Conversions (cs)
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as BS
-
-import Network.Haskoin.Crypto
-import Network.Haskoin.Util
-import Network.Haskoin.Internals (fromMnemonic)
-
-tests :: [Test]
-tests =
-    [ testGroup "Entropy to mnemonic sentence" toMnemonicTest
-    , testGroup "Mnemonic sentence to entropy" fromMnemonicTest
-    , testGroup "Mnemonic sentence to seed" mnemonicToSeedTest
-    ]
-
-toMnemonicTest :: [Test]
-toMnemonicTest = map f $ zip ents mss
-  where
-    f (e, m) = g (cs e) . assertEqual "" m . h $ e
-    g = testCase
-    h = fromRight . toMnemonic . fromJust . decodeHex
-
-fromMnemonicTest :: [Test]
-fromMnemonicTest = map f $ zip ents mss
-  where
-    f (e, m) = g (cs e) . assertEqual "" e . h $ m
-    g = testCase
-    h = encodeHex . fromRight . fromMnemonic
-
-mnemonicToSeedTest :: [Test]
-mnemonicToSeedTest = map f $ zip mss seeds
-  where
-    f (m, s) = g s . assertEqual "" s . h $ m
-    g = testCase . (++ "...") . cs . BS.take 50
-    h = encodeHex . fromRight . mnemonicToSeed "TREZOR"
-
-
-ents :: [ByteString]
-ents =
-    [ "00000000000000000000000000000000"
-    , "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f"
-    , "80808080808080808080808080808080"
-    , "ffffffffffffffffffffffffffffffff"
-    , "000000000000000000000000000000000000000000000000"
-    , "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f"
-    , "808080808080808080808080808080808080808080808080"
-    , "ffffffffffffffffffffffffffffffffffffffffffffffff"
-    , "0000000000000000000000000000000000000000000000000000000000000000"
-    , "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f"
-    , "8080808080808080808080808080808080808080808080808080808080808080"
-    , "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-    , "77c2b00716cec7213839159e404db50d"
-    , "b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b"
-    , "3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982"
-    , "0460ef47585604c5660618db2e6a7e7f"
-    , "72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f"
-    , "2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416"
-    , "eaebabb2383351fd31d703840b32e9e2"
-    , "7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78"
-    , "4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef"
-    , "18ab19a9f54a9274f03e5209a2ac8a91"
-    , "18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4"
-    , "15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419"
-    ]
-
-mss :: [Mnemonic]
-mss =
-    [ "abandon abandon abandon abandon abandon abandon abandon abandon abandon\
-      \ abandon abandon about"
-    , "legal winner thank year wave sausage worth useful legal winner thank\
-      \ yellow"
-    , "letter advice cage absurd amount doctor acoustic avoid letter advice\
-      \ cage above"
-    , "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong"
-    , "abandon abandon abandon abandon abandon abandon abandon abandon abandon\
-      \ abandon abandon abandon abandon abandon abandon abandon abandon agent"
-    , "legal winner thank year wave sausage worth useful legal winner thank\
-      \ year wave sausage worth useful legal will"
-    , "letter advice cage absurd amount doctor acoustic avoid letter advice\
-      \ cage absurd amount doctor acoustic avoid letter always"
-    , "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo\
-      \ when"
-    , "abandon abandon abandon abandon abandon abandon abandon abandon abandon\
-      \ abandon abandon abandon abandon abandon abandon abandon abandon abandon\
-      \ abandon abandon abandon abandon abandon art"
-    , "legal winner thank year wave sausage worth useful legal winner thank\
-      \ year wave sausage worth useful legal winner thank year wave sausage\
-      \ worth title"
-    , "letter advice cage absurd amount doctor acoustic avoid letter advice\
-      \ cage absurd amount doctor acoustic avoid letter advice cage absurd\
-      \ amount doctor acoustic bless"
-    , "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo\
-      \ zoo zoo zoo zoo zoo vote"
-    , "jelly better achieve collect unaware mountain thought cargo oxygen act\
-      \ hood bridge"
-    , "renew stay biology evidence goat welcome casual join adapt armor shuffle\
-      \ fault little machine walk stumble urge swap"
-    , "dignity pass list indicate nasty swamp pool script soccer toe leaf photo\
-      \ multiply desk host tomato cradle drill spread actor shine dismiss\
-      \ champion exotic"
-    , "afford alter spike radar gate glance object seek swamp infant panel\
-      \ yellow"
-    , "indicate race push merry suffer human cruise dwarf pole review arch keep\
-      \ canvas theme poem divorce alter left"
-    , "clutch control vehicle tonight unusual clog visa ice plunge glimpse\
-      \ recipe series open hour vintage deposit universe tip job dress radar\
-      \ refuse motion taste"
-    , "turtle front uncle idea crush write shrug there lottery flower risk\
-      \ shell"
-    , "kiss carry display unusual confirm curtain upgrade antique rotate hello\
-      \ void custom frequent obey nut hole price segment"
-    , "exile ask congress lamp submit jacket era scheme attend cousin alcohol\
-      \ catch course end lucky hurt sentence oven short ball bird grab wing top"
-    , "board flee heavy tunnel powder denial science ski answer betray cargo\
-      \ cat"
-    , "board blade invite damage undo sun mimic interest slam gaze truly\
-      \ inherit resist great inject rocket museum chief"
-    , "beyond stage sleep clip because twist token leaf atom beauty genius food\
-      \ business side grid unable middle armed observe pair crouch tonight away\
-      \ coconut"
-    ]
-
-seeds :: [ByteString]
-seeds =
-    [ "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a69\
-      \87599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04"
-    , "2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6fa457fe1\
-      \296106559a3c80937a1c1069be3a3a5bd381ee6260e8d9739fce1f607"
-    , "d71de856f81a8acc65e6fc851a38d4d7ec216fd0796d0a6827a3ad6ed5511a30fa280f1\
-      \2eb2e47ed2ac03b5c462a0358d18d69fe4f985ec81778c1b370b652a8"
-    , "ac27495480225222079d7be181583751e86f571027b0497b5b5d11218e0a8a133325729\
-      \17f0f8e5a589620c6f15b11c61dee327651a14c34e18231052e48c069"
-    , "035895f2f481b1b0f01fcf8c289c794660b289981a78f8106447707fdd9666ca06da5a9\
-      \a565181599b79f53b844d8a71dd9f439c52a3d7b3e8a79c906ac845fa"
-    , "f2b94508732bcbacbcc020faefecfc89feafa6649a5491b8c952cede496c214a0c7b3c3\
-      \92d168748f2d4a612bada0753b52a1c7ac53c1e93abd5c6320b9e95dd"
-    , "107d7c02a5aa6f38c58083ff74f04c607c2d2c0ecc55501dadd72d025b751bc27fe913f\
-      \fb796f841c49b1d33b610cf0e91d3aa239027f5e99fe4ce9e5088cd65"
-    , "0cd6e5d827bb62eb8fc1e262254223817fd068a74b5b449cc2f667c3f1f985a76379b43\
-      \348d952e2265b4cd129090758b3e3c2c49103b5051aac2eaeb890a528"
-    , "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4\
-      \d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8"
-    , "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146a\
-      \d717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87"
-    , "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61a\
-      \f0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f"
-    , "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0\
-      \a5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad"
-    , "b5b6d0127db1a9d2226af0c3346031d77af31e918dba64287a1b44b8ebf63cdd52676f6\
-      \72a290aae502472cf2d602c051f3e6f18055e84e4c43897fc4e51a6ff"
-    , "9248d83e06f4cd98debf5b6f010542760df925ce46cf38a1bdb4e4de7d21f5c39366941\
-      \c69e1bdbf2966e0f6e6dbece898a0e2f0a4c2b3e640953dfe8b7bbdc5"
-    , "ff7f3184df8696d8bef94b6c03114dbee0ef89ff938712301d27ed8336ca89ef9635da2\
-      \0af07d4175f2bf5f3de130f39c9d9e8dd0472489c19b1a020a940da67"
-    , "65f93a9f36b6c85cbe634ffc1f99f2b82cbb10b31edc7f087b4f6cb9e976e9faf76ff41\
-      \f8f27c99afdf38f7a303ba1136ee48a4c1e7fcd3dba7aa876113a36e4"
-    , "3bbf9daa0dfad8229786ace5ddb4e00fa98a044ae4c4975ffd5e094dba9e0bb289349db\
-      \e2091761f30f382d4e35c4a670ee8ab50758d2c55881be69e327117ba"
-    , "fe908f96f46668b2d5b37d82f558c77ed0d69dd0e7e043a5b0511c48c2f1064694a956f\
-      \86360c93dd04052a8899497ce9e985ebe0c8c52b955e6ae86d4ff4449"
-    , "bdfb76a0759f301b0b899a1e3985227e53b3f51e67e3f2a65363caedf3e32fde42a66c4\
-      \04f18d7b05818c95ef3ca1e5146646856c461c073169467511680876c"
-    , "ed56ff6c833c07982eb7119a8f48fd363c4a9b1601cd2de736b01045c5eb8ab4f57b079\
-      \403485d1c4924f0790dc10a971763337cb9f9c62226f64fff26397c79"
-    , "095ee6f817b4c2cb30a5a797360a81a40ab0f9a4e25ecd672a3f58a0b5ba0687c096a6b\
-      \14d2c0deb3bdefce4f61d01ae07417d502429352e27695163f7447a8c"
-    , "6eff1bb21562918509c73cb990260db07c0ce34ff0e3cc4a8cb3276129fbcb300bddfe0\
-      \05831350efd633909f476c45c88253276d9fd0df6ef48609e8bb7dca8"
-    , "f84521c777a13b61564234bf8f8b62b3afce27fc4062b51bb5e62bdfecb23864ee6ecf0\
-      \7c1d5a97c0834307c5c852d8ceb88e7c97923c0a3b496bedd4e5f88a9"
-    , "b15509eaa2d09d3efd3e006ef42151b30367dc6e3aa5e44caba3fe4d3e352e65101fbdb\
-      \86a96776b91946ff06f8eac594dc6ee1d3e82a42dfe1b40fef6bcc3fd"
-    ]
diff --git a/tests/Network/Haskoin/Crypto/Units.hs b/tests/Network/Haskoin/Crypto/Units.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Crypto/Units.hs
+++ /dev/null
@@ -1,248 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Network.Haskoin.Crypto.Units (tests) where
-
-import Test.HUnit (Assertion, assertBool)
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-
-import Control.Monad (replicateM_)
-import Control.Monad.Trans (liftIO)
-
-import Data.Maybe (fromJust, isJust, isNothing)
-import Data.ByteString (ByteString)
-import qualified Data.ByteString.Lazy as B 
-import qualified Data.Binary as Bin
-import qualified Data.ByteString.Char8 as C (pack)
-
-import qualified Crypto.Secp256k1 as EC (SecKey, exportCompactSig)
-
-import Network.Haskoin.Crypto
-import Network.Haskoin.Util
-import Network.Haskoin.Internals (PrvKeyI(..), PubKeyI(..), Signature(..))
-
--- Unit tests copied from bitcoind implementation
--- https://github.com/bitcoin/bitcoin/blob/master/src/test/key_tests.cpp
-
-strSecret1 :: ByteString
-strSecret1  = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj"
-
-strSecret2 :: ByteString
-strSecret2  = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3"
-
-strSecret1C :: ByteString
-strSecret1C = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw"
-
-strSecret2C :: ByteString
-strSecret2C = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g"
-
-addr1 :: ByteString
-addr1  = "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ"
-
-addr2 :: ByteString
-addr2  = "1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ"
-
-addr1C :: ByteString
-addr1C = "1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs"
-
-addr2C :: ByteString
-addr2C = "1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs"
-
-strAddressBad :: ByteString
-strAddressBad = "1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF"
-
-sigMsg :: [ByteString]
-sigMsg =
-    [ mconcat ["Very secret message ", (C.pack $ show (i :: Int)), ": 11"]
-    | i <- [0..15]
-    ]
-
-sec1 :: PrvKey
-sec1  = fromJust $ fromWif strSecret1
-
-sec2 :: PrvKey
-sec2  = fromJust $ fromWif strSecret2
-
-sec1C :: PrvKey
-sec1C = fromJust $ fromWif strSecret1C
-
-sec2C :: PrvKey
-sec2C = fromJust $ fromWif strSecret2C
-
-pub1 :: PubKey
-pub1  = derivePubKey sec1
-
-pub2 :: PubKey
-pub2  = derivePubKey sec2
-
-pub1C :: PubKey
-pub1C = derivePubKey sec1C
-
-pub2C :: PubKey
-pub2C = derivePubKey sec2C
-
-tests :: [Test]
-tests =
-    [ testGroup "ECDSA PRNG unit tests"
-        [ testCase "genPrvKey produces unique keys" uniqueKeys
-        ]
-    , testGroup "bitcoind /src/test/key_tests.cpp" $
-        [ testCase "Decode Valid WIF" checkPrivkey
-        , testCase "Decode Invalid WIF" checkInvalidKey
-        , testCase "Check private key compression" checkPrvKeyCompressed
-        , testCase "Check public key compression" checkKeyCompressed
-        , testCase "Check matching address" checkMatchingAddress
-        ] ++
-        ( map (\x -> (testCase ("Check sig: " ++ (show x))
-                (checkSignatures $ doubleHash256 x))) sigMsg )
-    , testGroup "Trezor RFC 6979 Test Vectors"
-        [ testCase "RFC 6979 Test Vector 1" (testSigning $ detVec !! 0)
-        , testCase "RFC 6979 Test Vector 2" (testSigning $ detVec !! 1)
-        , testCase "RFC 6979 Test Vector 3" (testSigning $ detVec !! 2)
-        , testCase "RFC 6979 Test Vector 4" (testSigning $ detVec !! 3)
-        , testCase "RFC 6979 Test Vector 5" (testSigning $ detVec !! 4)
-        , testCase "RFC 6979 Test Vector 6" (testSigning $ detVec !! 5)
-        , testCase "RFC 6979 Test Vector 7" (testSigning $ detVec !! 6)
-        , testCase "RFC 6979 Test Vector 8" (testSigning $ detVec !! 7)
-        , testCase "RFC 6979 Test Vector 9" (testSigning $ detVec !! 8)
-        , testCase "RFC 6979 Test Vector 10" (testSigning $ detVec !! 9)
-        , testCase "RFC 6979 Test Vector 11" (testSigning $ detVec !! 10)
-        , testCase "RFC 6979 Test Vector 12" (testSigning $ detVec !! 11)
-        ]
-    ]
-
-{- ECDSA PRNG unit tests -}
-
-uniqueKeys :: Assertion
-uniqueKeys = do
-    (k1,k2,k3) <- liftIO $ withSource getEntropy $ do
-        a <- genPrvKey
-        b <- genPrvKey
-        replicateM_ 20 genPrvKey
-        c <- genPrvKey
-        return (a,b,c)
-    assertBool "DiffKey" $ k1 /= k2 && k1 /= k3 && k2 /= k3
-
-{- bitcoind /src/test/key_tests.cpp -}
-
-checkPrivkey :: Assertion
-checkPrivkey = do
-    assertBool "Key 1"  $ isJust $ fromWif strSecret1
-    assertBool "Key 2"  $ isJust $ fromWif strSecret2
-    assertBool "Key 1C" $ isJust $ fromWif strSecret1C
-    assertBool "Key 2C" $ isJust $ fromWif strSecret2C
-
-checkInvalidKey :: Assertion
-checkInvalidKey =
-    assertBool "Bad key" $ isNothing $ fromWif strAddressBad
-
-checkPrvKeyCompressed :: Assertion
-checkPrvKeyCompressed = do
-    assertBool "Key 1"  $ not $ prvKeyCompressed sec1
-    assertBool "Key 2"  $ not $ prvKeyCompressed sec2
-    assertBool "Key 1C" $ prvKeyCompressed sec1C
-    assertBool "Key 2C" $ prvKeyCompressed sec2C
-
-checkKeyCompressed :: Assertion
-checkKeyCompressed = do
-    assertBool "Key 1"  $ not $ pubKeyCompressed pub1
-    assertBool "Key 2"  $ not $ pubKeyCompressed pub2
-    assertBool "Key 1C" $ pubKeyCompressed pub1C
-    assertBool "Key 2C" $ pubKeyCompressed pub2C
-
-checkMatchingAddress :: Assertion
-checkMatchingAddress = do
-    assertBool "Key 1"  $ addr1  == (addrToBase58 $ pubKeyAddr pub1)
-    assertBool "Key 2"  $ addr2  == (addrToBase58 $ pubKeyAddr pub2)
-    assertBool "Key 1C" $ addr1C == (addrToBase58 $ pubKeyAddr pub1C)
-    assertBool "Key 2C" $ addr2C == (addrToBase58 $ pubKeyAddr pub2C)
-
-checkSignatures :: Hash256 -> Assertion
-checkSignatures h = do
-    let sign1  = signMsg h sec1
-        sign2  = signMsg h sec2
-        sign1C = signMsg h sec1C
-        sign2C = signMsg h sec2C
-    assertBool "Key 1, Sign1"   $ verifySig h sign1 pub1
-    assertBool "Key 1, Sign2"   $ not $ verifySig h sign2 pub1
-    assertBool "Key 1, Sign1C"  $ verifySig h sign1C pub1
-    assertBool "Key 1, Sign2C"  $ not $ verifySig h sign2C pub1
-    assertBool "Key 2, Sign1"   $ not $ verifySig h sign1 pub2
-    assertBool "Key 2, Sign2"   $ verifySig h sign2 pub2
-    assertBool "Key 2, Sign1C"  $ not $ verifySig h sign1C pub2
-    assertBool "Key 2, Sign2C"  $ verifySig h sign2C pub2
-    assertBool "Key 1C, Sign1"  $ verifySig h sign1 pub1C
-    assertBool "Key 1C, Sign2"  $ not $ verifySig h sign2 pub1C
-    assertBool "Key 1C, Sign1C" $ verifySig h sign1C pub1C
-    assertBool "Key 1C, Sign2C" $ not $ verifySig h sign2C pub1C
-    assertBool "Key 2C, Sign1"  $ not $ verifySig h sign1 pub2C
-    assertBool "Key 2C, Sign2"  $ verifySig h sign2 pub2C
-    assertBool "Key 2C, Sign1C" $ not $ verifySig h sign1C pub2C
-    assertBool "Key 2C, Sign2C" $ verifySig h sign2C pub2C
-
-
-{- Trezor RFC 6979 Test Vectors -}
--- github.com/trezor/python-ecdsa/blob/master/ecdsa/test_pyecdsa.py
-
-detVec :: [(EC.SecKey, ByteString, ByteString)]
-detVec =
-    [
-      ( "0000000000000000000000000000000000000000000000000000000000000001"
-      , "Satoshi Nakamoto"
-      , "934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d82442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5"
-      )
-    , ( "0000000000000000000000000000000000000000000000000000000000000001"
-      , "All those moments will be lost in time, like tears in rain. Time to die..."
-      , "8600dbd41e348fe5c9465ab92d23e3db8b98b873beecd930736488696438cb6b547fe64427496db33bf66019dacbf0039c04199abb0122918601db38a72cfc21"
-      )
-    , ( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140"
-      , "Satoshi Nakamoto"
-      , "fd567d121db66e382991534ada77a6bd3106f0a1098c231e47993447cd6af2d06b39cd0eb1bc8603e159ef5c20a5c8ad685a45b06ce9bebed3f153d10d93bed5"
-      )
-    , ( "f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181"
-      , "Alan Turing"
-      , "7063ae83e7f62bbb171798131b4a0564b956930092b33b07b395615d9ec7e15c58dfcc1e00a35e1572f366ffe34ba0fc47db1e7189759b9fb233c5b05ab388ea"
-      )
-    , ( "e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2"
-      , "There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!"
-      , "b552edd27580141f3b2a5463048cb7cd3e047b97c9f98076c32dbdf85a68718b279fa72dd19bfae05577e06c7c0c1900c371fcd5893f7e1d56a37d30174671f6"
-      )
-    , ( "0000000000000000000000000000000000000000000000000000000000000001"
-      , "Everything should be made as simple as possible, but not simpler."
-      , "33a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c96f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262"
-      )
-    , ( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140"
-      , "Equations are more important to me, because politics is for the present, but an equation is something for eternity."
-      , "54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
-      )
-    , ( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140"
-      , "Not only is the Universe stranger than we think, it is stranger than we can think."
-      , "ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd06fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283"
-      )
-    , ( "0000000000000000000000000000000000000000000000000000000000000001"
-      , "How wonderful that we have met with a paradox. Now we have some hope of making progress."
-      , "c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d375afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3"
-      )
-    , ( "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64"
-      , "Computer science is no more about computers than astronomy is about telescopes."
-      , "7186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d0de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6"
-      )
-    , ( "00000000000000000000000000007246174ab1e92e9149c6e446fe194d072637"
-      , "...if you aren't, at any given time, scandalized by code you wrote five or even three years ago, you're not learning anywhere near enough"
-      , "fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda4870e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37"
-      )
-    , ( "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3"
-      , "The question of whether computers can think is like the question of whether submarines can swim."
-      , "cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf906ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef"
-      )
-    ]
-
-testSigning :: (EC.SecKey, ByteString, ByteString) -> Assertion
-testSigning (prv, msg, str) = do
-    assertBool "RFC 6979 Vector" $ res == fromJust (decodeHex str)
-    assertBool "Valid sig" $ verifySig msg' sig (derivePubKey prv')
-  where
-    sig@(Signature g) = signMsg msg' prv'
-    msg' = hash256 msg
-    prv' = makePrvKey prv
-    compact = EC.exportCompactSig g
-    res = B.toStrict $ Bin.encode compact
diff --git a/tests/Network/Haskoin/Json/Tests.hs b/tests/Network/Haskoin/Json/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Json/Tests.hs
+++ /dev/null
@@ -1,35 +0,0 @@
-module Network.Haskoin.Json.Tests (tests) where
-
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.Aeson (FromJSON, ToJSON, decode, encode)
-import Data.HashMap.Strict (singleton)
-
-import Network.Haskoin.Test
-
-tests :: [Test]
-tests =
-    [ testGroup "Serialize & de-serialize haskoin types to JSON"
-        [ testProperty "ScriptOutput" $ \(ArbitraryScriptOutput x) -> metaID x
-        , testProperty "OutPoint" $ \(ArbitraryOutPoint x) -> metaID x
-        , testProperty "Address" $ \(ArbitraryAddress x) -> metaID x
-        , testProperty "Tx" $ \(ArbitraryTx x) -> metaID x
-        , testProperty "TxHash" $ \(ArbitraryTxHash x) -> metaID x
-        , testProperty "BlockHash" $ \(ArbitraryBlockHash x) -> metaID x
-        , testProperty "SigHash" $ \(ArbitrarySigHash x) -> metaID x
-        , testProperty "SigInput" $ \(ArbitrarySigInput x _) -> metaID x
-        , testProperty "PubKey" $ \(ArbitraryPubKey _ x) -> metaID x
-        , testProperty "PubKeyC" $ \(ArbitraryPubKeyC _ x) -> metaID x
-        , testProperty "PubKeyU" $ \(ArbitraryPubKeyU _ x) -> metaID x
-        , testProperty "XPrvKey" $ \(ArbitraryXPrvKey x) -> metaID x
-        , testProperty "XPubKey" $ \(ArbitraryXPubKey _ x) -> metaID x
-        , testProperty "DerivPath" $ \(ArbitraryDerivPath x) -> metaID x
-        , testProperty "ParsedPath" $ \(ArbitraryParsedPath x) -> metaID x
-        ]
-    ]
-
-metaID :: (FromJSON a, ToJSON a, Eq a) => a -> Bool
-metaID x = (decode . encode) (singleton ("object" :: String) x) ==
-    Just (singleton ("object" :: String) x)
-
diff --git a/tests/Network/Haskoin/Node/Units.hs b/tests/Network/Haskoin/Node/Units.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Node/Units.hs
+++ /dev/null
@@ -1,73 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Network.Haskoin.Node.Units (tests) where
-
-import Test.HUnit (Assertion, assertBool)
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-
-import Data.Maybe (fromJust)
-import Data.Serialize (encode)
-
-import Network.Haskoin.Crypto
-import Network.Haskoin.Node
-import Network.Haskoin.Util
-
-tests :: [Test]
-tests =
-    [ -- Test cases come from bitcoind /src/test/bloom_tests.cpp
-      testGroup "Bloom Filters"
-        [ testCase "Bloom Filter Vector 1" bloomFilter1
-        , testCase "Bloom Filter Vector 2" bloomFilter2
-        , testCase "Bloom Filter Vector 3" bloomFilter3
-        ]
-    ]
-
-bloomFilter1 :: Assertion
-bloomFilter1 = do
-    assertBool "Bloom filter doesn't contain vector 1" $ bloomContains f1 v1
-    assertBool "Bloom filter contains something it should not" $
-        not $ bloomContains f1 v2
-    assertBool "Bloom filter doesn't contain vector 3" $ bloomContains f3 v3
-    assertBool "Bloom filter doesn't contain vector 4" $ bloomContains f4 v4
-    assertBool "Bloom filter serialization is incorrect" $ (encode f4) == bs
-  where
-    f0 = bloomCreate 3 0.01 0 BloomUpdateAll
-    f1 = bloomInsert f0 v1
-    f3 = bloomInsert f1 v3
-    f4 = bloomInsert f3 v4
-    v1 = fromJust $ decodeHex "99108ad8ed9bb6274d3980bab5a85c048f0950c8"
-    v2 = fromJust $ decodeHex "19108ad8ed9bb6274d3980bab5a85c048f0950c8"
-    v3 = fromJust $ decodeHex "b5a2c786d9ef4658287ced5914b37a1b4aa32eee"
-    v4 = fromJust $ decodeHex "b9300670b4c5366e95b2699e8b18bc75e5f729c5"
-    bs = fromJust $ decodeHex "03614e9b050000000000000001"
-
-bloomFilter2 :: Assertion
-bloomFilter2 = do
-    assertBool "Bloom filter doesn't contain vector 1" $ bloomContains f1 v1
-    assertBool "Bloom filter contains something it should not" $
-        not $ bloomContains f1 v2
-    assertBool "Bloom filter doesn't contain vector 3" $ bloomContains f3 v3
-    assertBool "Bloom filter doesn't contain vector 4" $ bloomContains f4 v4
-    assertBool "Bloom filter serialization is incorrect" $ (encode f4) == bs
-  where
-    f0 = bloomCreate 3 0.01 2147483649 BloomUpdateAll
-    f1 = bloomInsert f0 v1
-    f3 = bloomInsert f1 v3
-    f4 = bloomInsert f3 v4
-    v1 = fromJust $ decodeHex "99108ad8ed9bb6274d3980bab5a85c048f0950c8"
-    v2 = fromJust $ decodeHex "19108ad8ed9bb6274d3980bab5a85c048f0950c8"
-    v3 = fromJust $ decodeHex "b5a2c786d9ef4658287ced5914b37a1b4aa32eee"
-    v4 = fromJust $ decodeHex "b9300670b4c5366e95b2699e8b18bc75e5f729c5"
-    bs = fromJust $ decodeHex "03ce4299050000000100008001"
-
-bloomFilter3 :: Assertion
-bloomFilter3 = do
-    assertBool "Bloom filter serialization is incorrect" $ (encode f2) == bs
-  where
-    f0 = bloomCreate 2 0.001 0 BloomUpdateAll
-    f1 = bloomInsert f0 $ encode p
-    f2 = bloomInsert f1 $ encode $ getAddrHash $ pubKeyAddr p
-    k = fromJust $ fromWif "5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C"
-    p = derivePubKey k
-    bs = fromJust $ decodeHex "038fc16b080000000000000001"
-
diff --git a/tests/Network/Haskoin/Script/Tests.hs b/tests/Network/Haskoin/Script/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Script/Tests.hs
+++ /dev/null
@@ -1,402 +0,0 @@
-module Network.Haskoin.Script.Tests
-( tests
-, execScriptIO
-, testValid
-, testInvalid
-, runTests
-) where
-
-import Test.QuickCheck.Property (Property, (==>))
-import Test.Framework (Test, testGroup, buildTest)
-import Test.Framework.Providers.HUnit (testCase)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-import Test.Framework.Runners.Console (defaultMainWithArgs)
-import qualified Test.HUnit as HUnit (assertFailure, assertBool)
-
-import Control.Monad (when)
-
-import Data.Bits (testBit)
-import Data.List (isPrefixOf)
-import Data.List.Split ( splitOn )
-import Data.Char (ord)
-import Data.Maybe (catMaybes, isNothing)
-import Data.Int (Int64)
-import Data.Word (Word8, Word32)
-import qualified Data.Aeson as A (decode)
-import qualified Data.ByteString.Lazy.Char8 as C (readFile)
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as BS
-    ( singleton
-    , length
-    , tail
-    , head
-    , pack
-    , unpack
-    , empty
-    )
-import qualified Data.ByteString.Char8 as C (putStrLn)
-import Data.Serialize (decode, encode)
-
-import Numeric (readHex)
-import Text.Read (readMaybe)
-
-import Network.Haskoin.Test
-import Network.Haskoin.Transaction
-import Network.Haskoin.Script
-import Network.Haskoin.Crypto
-import Network.Haskoin.Util
-import Network.Haskoin.Internals
-    ( Flag
-    , runStack
-    , dumpStack
-    , decodeInt
-    , encodeInt
-    , decodeFullInt
-    , cltvDecodeInt
-    , decodeBool
-    , encodeBool
-    , execScript
-    )
-
-tests :: [Test]
-tests =
-    [ testGroup "Script Parser"
-        [ testProperty "decode . encode OP_1 .. OP_16" testScriptOpInt
-        , testProperty "decode . encode ScriptOutput" testScriptOutput
-        , testProperty "decode . encode ScriptInput" testScriptInput
-        , testProperty "sorting MultiSig scripts" testSortMulSig
-        ]
-    , testGroup "Script SigHash"
-        [ testProperty "canonical signatures" $
-            \(ArbitraryTxSignature _ _ sig) -> testCanonicalSig sig
-        , testProperty "decode SigHash from Word8" binSigHashByte
-        , testProperty "encodeSigHash32 is 4 bytes long" testEncodeSH32
-        , testProperty "decode . encode TxSignature" $
-            \(ArbitraryTxSignature _ _ sig) -> binTxSig sig
-        , testProperty "decodeCanonical . encode TxSignature" $
-            \(ArbitraryTxSignature _ _ sig) -> binTxSigCanonical sig
-        , testProperty "Testing txSigHash with SigSingle" testSigHashOne
-        ]
-    , testGroup "Integer Types"
-        [ testProperty "decodeInt . encodeInt Int"  testEncodeInt
-        , testProperty "decodeFullInt . encodeInt Int"  testEncodeInt64
-        , testProperty "cltvDecodeInt . encodeInt Int" testEncodeCltv
-        , testProperty "decodeBool . encodeBool Bool" testEncodeBool
-        ]
-    , testFile "Canonical Valid Script Test Cases"
-               "tests/data/script_valid.json"
-               True
-    , testFile "Canonical Invalid Script Test Cases"
-               "tests/data/script_invalid.json"
-               False
-    ]
-
-{- Script Parser -}
-
-testScriptOpInt :: ArbitraryIntScriptOp -> Bool
-testScriptOpInt (ArbitraryIntScriptOp i) =
-    (intToScriptOp <$> scriptOpToInt i) == Right i
-
-testScriptOutput :: ArbitraryScriptOutput -> Bool
-testScriptOutput (ArbitraryScriptOutput so) =
-    decodeOutput (encodeOutput so) == Right so
-
-testScriptInput :: ArbitraryScriptInput -> Bool
-testScriptInput (ArbitraryScriptInput si) =
-    decodeInput (encodeInput si) == Right si
-
-testSortMulSig :: ArbitraryMSOutput -> Bool
-testSortMulSig (ArbitraryMSOutput out) =
-    snd $ foldl f (head pubs,True) $ tail pubs
-  where
-    pubs = getOutputMulSigKeys $ sortMulSig out
-    f (a,t) b | t && encode a <= encode b = (b,True)
-              | otherwise                   = (b,False)
-
-{- Script SigHash -}
-
-testCanonicalSig :: TxSignature -> Bool
-testCanonicalSig ts@(TxSignature _ sh)
-    | isSigUnknown sh = isLeft $ decodeCanonicalSig bs
-    | otherwise =
-        isRight (decodeCanonicalSig bs) && isCanonicalHalfOrder (txSignature ts)
-  where
-    bs = encodeSig ts
-
-binSigHashByte :: Word8 -> Bool
-binSigHashByte w
-    | w == 0x01 = res == SigAll False
-    | w == 0x02 = res == SigNone False
-    | w == 0x03 = res == SigSingle False
-    | w == 0x81 = res == SigAll True
-    | w == 0x82 = res == SigNone True
-    | w == 0x83 = res == SigSingle True
-    | testBit w 7 = res == SigUnknown True w
-    | otherwise = res == SigUnknown False w
-  where
-    res = fromRight . decode $ BS.singleton w
-
-testEncodeSH32 :: ArbitrarySigHash -> Bool
-testEncodeSH32 (ArbitrarySigHash sh) =
-    BS.length bs == 4 &&
-    BS.head bs == (BS.head $ encode sh) &&
-    BS.tail bs == BS.pack [0,0,0]
-  where
-    bs = encodeSigHash32 sh
-
-binTxSig :: TxSignature -> Bool
-binTxSig ts = decodeSig (encodeSig ts) == Right ts
-
-binTxSigCanonical :: TxSignature -> Bool
-binTxSigCanonical ts@(TxSignature _ sh)
-    | isSigUnknown sh = isLeft $ decodeCanonicalSig $ encodeSig ts
-    | otherwise = (fromRight $ decodeCanonicalSig $ encodeSig ts) == ts
-
-testSigHashOne :: ArbitraryTx -> ArbitraryScript -> Bool -> Property
-testSigHashOne (ArbitraryTx tx) (ArbitraryScript s) acp = not (null $ txIn tx) ==>
-    if length (txIn tx) > length (txOut tx)
-        then res == one
-        else res /= one
-  where
-    res = txSigHash tx s (length (txIn tx) - 1) (SigSingle acp)
-    one = "0100000000000000000000000000000000000000000000000000000000000000"
-
-{- Script Evaluation Primitives -}
-
-testEncodeInt :: Int64 -> Bool
-testEncodeInt i
-    | i >  0x7fffffff = isNothing i'
-    | i < -0x7fffffff = isNothing i'
-    | otherwise       = i' == Just i
-  where
-    i' = decodeInt $ encodeInt i
-
-testEncodeCltv :: Int64 -> Bool
-testEncodeCltv i
-    -- As 'cltvEncodeInt' is just a wrapper for 'encodeInt',
-    -- we use 'encodeInt' for encoding, to simultaneously
-    -- test the handling of out-of-range integers by 'cltvDecodeInt'.
-    | i < 0 || i > fromIntegral (maxBound :: Word32) =
-        isNothing $ cltvDecodeInt (encodeInt i)
-    | otherwise =
-        cltvDecodeInt (encodeInt i) == Just (fromIntegral i)
-
-testEncodeInt64 :: Int64 -> Bool
-testEncodeInt64 i = decodeFullInt (encodeInt i) == Just i
-
-testEncodeBool :: Bool -> Bool
-testEncodeBool b = decodeBool (encodeBool b) == b
-
-{- Script Evaluation -}
-
-rejectSignature :: SigCheck
-rejectSignature _ _ _ = False
-
-{- Parse tests from bitcoin-qt repository -}
-
-type ParseError = String
-
-parseHex' :: String -> Maybe [Word8]
-parseHex' (a:b:xs) = case readHex $ [a, b] :: [(Integer, String)] of
-                      [(i, "")] -> case parseHex' xs of
-                                    Just ops -> Just $ fromIntegral i:ops
-                                    Nothing -> Nothing
-                      _ -> Nothing
-parseHex' [_] = Nothing
-parseHex' [] = Just []
-
-parseFlags :: String -> [ Flag ]
-parseFlags "" = []
-parseFlags s = map read . splitOn "," $ s
-
-parseScript :: String -> Either ParseError Script
-parseScript scriptString =
-      do bytes <- BS.pack <$> parseBytes scriptString
-         script <- decodeScript bytes
-         when (encode script /= bytes) $
-            Left "encode script /= bytes"
-         when (fromRight (decode $ encode script) /= script) $
-            Left "decode (encode script) /= script"
-         return script
-      where
-          decodeScript bytes = case decode bytes of
-            Left e -> Left $ "decode error: " ++ e
-            Right (Script s) -> Right $ Script s
-          parseBytes :: String -> Either ParseError [Word8]
-          parseBytes string = concat <$> mapM parseToken (words string)
-          parseToken :: String -> Either ParseError [Word8]
-          parseToken tok =
-              case alternatives of
-                    (ops:_) -> Right ops
-                    _ -> Left $ "unknown token " ++ tok
-              where alternatives :: [[Word8]]
-                    alternatives = catMaybes  [ parseHex
-                                              , parseInt
-                                              , parseQuote
-                                              , parseOp
-                                              ]
-                    parseHex | "0x" `isPrefixOf` tok = parseHex' (drop 2 tok)
-                             | otherwise = Nothing
-                    parseInt = fromInt . fromIntegral <$>
-                               (readMaybe tok :: Maybe Integer)
-                    parseQuote | tok == "''" = Just [0]
-                               | (head tok) == '\'' && (last tok) == '\'' =
-                                 Just $ encodeBytes $ opPushData $ BS.pack
-                                      $ map (fromIntegral . ord)
-                                      $ init . tail $ tok
-                               | otherwise = Nothing
-                    fromInt :: Int64 -> [Word8]
-                    fromInt n | n ==  0 = [0x00]
-                              | n == -1 = [0x4f]
-                              | 1 <= n && n <= 16 = [0x50 + fromIntegral n]
-                              | otherwise = encodeBytes
-                                                $ opPushData $ BS.pack
-                                                $ encodeInt n
-                    parseOp = encodeBytes <$> (readMaybe $ "OP_" ++ tok)
-                    encodeBytes = BS.unpack . encode
-
-testFile :: String -> String -> Bool -> Test
-testFile groupLabel path expected = buildTest $ do
-    dat <- C.readFile path
-    case (A.decode dat) :: Maybe [[String]] of
-        Nothing -> return $
-                    testCase groupLabel $
-                    HUnit.assertFailure $ "can't read test file " ++ path
-        Just testDefs -> return $ testGroup groupLabel
-                                $ map parseTest
-                                $ filterPureComments testDefs
-
-    where   parseTest :: [String] -> Test
-            parseTest s = case testParts s of
-                Nothing -> testCase "can't parse test case" $
-                               HUnit.assertFailure $ "json element " ++ show s
-                Just ( sig, pubKey, flags, label ) -> makeTest label sig pubKey flags
-
-            makeTest :: String -> String -> String -> String -> Test
-            makeTest label sig pubKey flags =
-                testCase label' $ case (parseScript sig, parseScript pubKey) of
-                    (Left e, _) -> parseError $ "can't parse sig: " ++
-                                                show sig ++ " error: " ++ e
-                    (_, Left e) -> parseError $ "can't parse key: " ++
-                                                show pubKey ++ " error: " ++ e
-                    (Right scriptSig, Right scriptPubKey) ->
-                        runTest scriptSig scriptPubKey ( parseFlags flags )
-
-                where label' =  if null label
-                                    then "sig: [" ++ sig ++ "] " ++
-                                        " pubKey: [" ++ pubKey ++ "] "
-                                    else " label: " ++ label
-
-            parseError message = HUnit.assertBool
-                                ("parse error in valid script: " ++ message)
-                                (expected == False)
-
-            filterPureComments = filter ( not . null . tail )
-
-            runTest scriptSig scriptPubKey scriptFlags =
-                HUnit.assertBool
-                  (" eval error: " ++ errorMessage)
-                  (expected == scriptPairTestExec scriptSig scriptPubKey scriptFlags)
-
-                where run f = f scriptSig scriptPubKey rejectSignature scriptFlags
-                      errorMessage = case run execScript of
-                        Left e -> show e
-                        Right _ -> " none"
-
--- | Splits the JSON test into the different parts.  No processing,
--- just handling the fact that comments may not be there or might have
--- junk before it.  Output is the tuple ( sig, pubKey, flags, comment
--- ) as strings
-testParts :: [String] -> Maybe (String, String, String, String)
-testParts l = let ( x, r ) = splitAt 3 l
-                  comment = if null r then "" else last r
-              in if length x < 3
-                 then Nothing
-                 else let ( sig:pubKey:flags:[] ) = x in
-                      Just ( sig, pubKey, flags, comment )
-
--- repl utils
-
-execScriptIO :: String -> String -> String -> IO ()
-execScriptIO sig key flgs = case (parseScript sig, parseScript key) of
-  (Left e, _) -> print $ "sig parse error: " ++ e
-  (_, Left e) -> print $ "key parse error: " ++ e
-  (Right scriptSig, Right scriptPubKey) ->
-      case execScript scriptSig scriptPubKey rejectSignature ( parseFlags flgs ) of
-          Left e -> putStrLn $ "error " ++ show e
-          Right p -> do putStrLn $ "successful execution"
-                        C.putStrLn $ dumpStack $ runStack p
-
-testValid :: Test
-testValid = testFile "Canonical Valid Script Test Cases"
-            "tests/data/script_valid.json" True
-
-testInvalid :: Test
-testInvalid = testFile "Canonical Valid Script Test Cases"
-              "tests/data/script_invalid.json" False
-
--- | Maximum value of sequence number
-maxSeqNum :: Word32
-maxSeqNum = 0xffffffff -- Perhaps this should be moved to constants.
-
--- | Null output used to create CoinbaseTx
-nullOutPoint :: OutPoint
-nullOutPoint =
-    OutPoint
-        { outPointHash  =
-            "0000000000000000000000000000000000000000000000000000000000000000"
-        , outPointIndex = -1
-        }
-
--- | Some of the scripts tests require transactions be built in a
--- standard way.  This function builds the crediting transaction.
--- Quoting the top comment of script_valid.json: "It is evaluated as
--- if there was a crediting coinbase transaction with two 0 pushes as
--- scriptSig, and one output of 0 satoshi and given scriptPubKey,
--- followed by a spending transaction which spends this output as only
--- input (and correct prevout hash), using the given scriptSig. All
--- nLockTimes are 0, all nSequences are max."
-buildCreditTx :: ByteString -> Tx
-buildCreditTx scriptPubKey =
-    createTx 1 [ txI ] [ txO ] 0
-  where
-    txO = TxOut { outValue = 0
-                , scriptOutput = scriptPubKey
-                }
-    txI = TxIn { prevOutput = nullOutPoint
-               , scriptInput = encode $ Script [ OP_0, OP_0 ]
-               , txInSequence = maxSeqNum
-               }
-
--- | Build a spending transaction for the tests.  Takes as input the
--- crediting transaction
-buildSpendTx :: ByteString  -- ScriptSig
-             -> Tx          -- Creditting Tx
-             -> Tx
-buildSpendTx scriptSig creditTx =
-    createTx 1 [ txI ] [ txO ] 0
-  where
-    txI = TxIn { prevOutput = OutPoint { outPointHash = txHash creditTx
-                                       , outPointIndex = 0
-                                       }
-               , scriptInput  = scriptSig
-               , txInSequence = maxSeqNum
-               }
-    txO = TxOut { outValue = 0, scriptOutput = BS.empty }
-
--- | Executes the test of a scriptSig, pubKeyScript pair, including
--- building the required transactions and verifying the spending
--- transaction.
-scriptPairTestExec :: Script    -- scriptSig
-                   -> Script    -- pubKey
-                   -> [ Flag ] -- Evaluation flags
-                   -> Bool
-scriptPairTestExec scriptSig pubKey flags =
-    let bsScriptSig = encode scriptSig
-        bsPubKey = encode pubKey
-        spendTx = buildSpendTx bsScriptSig ( buildCreditTx bsPubKey )
-    in verifySpend spendTx 0 pubKey flags
-
-runTests :: [Test] -> IO ()
-runTests ts = defaultMainWithArgs ts ["--hide-success"]
-
diff --git a/tests/Network/Haskoin/Script/Units.hs b/tests/Network/Haskoin/Script/Units.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Script/Units.hs
+++ /dev/null
@@ -1,124 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Network.Haskoin.Script.Units (tests) where
-
-import Test.HUnit (Assertion, assertBool)
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-
-import Data.Maybe (fromJust)
-import Data.ByteString (ByteString)
-import Data.Serialize (decode)
-
-import Network.Haskoin.Script
-import Network.Haskoin.Crypto
-import Network.Haskoin.Util
-
-tests :: [Test]
-tests =
-    [ testGroup "Canonical signatures"
-        (map canonicalVectorsMap $ zip canonicalVectors [0..])
-    , testGroup "Non-canonical signatures"
-        (map notCanonicalVectorsMap $ zip notCanonicalVectors [0..])
-    , testGroup "Multi Signatures"
-        (map mapMulSigVector $ zip mulSigVectors [0..])
-    , testGroup "Signature decoding"
-        (map sigDecodeMap $ zip scriptSigSignatures [0..])
-    ]
-
-canonicalVectorsMap :: (ByteString, Int) -> Test.Framework.Test
-canonicalVectorsMap (_, i) =
-    testCase ("Canonical Sig " ++ (show i)) func
-  where
-    func = testCanonicalSig $ canonicalVectors !! i
-
-notCanonicalVectorsMap :: (ByteString, Int) -> Test.Framework.Test
-notCanonicalVectorsMap (_, i) =
-    testCase ("Not canonical Sig " ++ show i) func
-  where
-    func = testNotCanonicalSig $ notCanonicalVectors !! i
-
-sigDecodeMap :: (ByteString, Int) -> Test.Framework.Test
-sigDecodeMap (_, i) =
-    testCase ("Signature " ++ show i) func
-  where
-    func = testSigDecode $ scriptSigSignatures !! i
-
-testCanonicalSig :: ByteString -> Assertion
-testCanonicalSig str =
-    assertBool "    > Canonical Sig" $ isRight $ decodeCanonicalSig bs
-  where
-    bs = fromJust $ decodeHex str
-
-testNotCanonicalSig :: ByteString -> Assertion
-testNotCanonicalSig str =
-    assertBool "    > Not canonical sig" $ isLeft $ decodeCanonicalSig bs
-  where
-    bs = fromJust $ decodeHex str
-
-mapMulSigVector :: ((ByteString, ByteString), Int) -> Test.Framework.Test
-mapMulSigVector (v, i) =
-    testCase name $ runMulSigVector v
-  where
-    name = "MultiSignature vector " ++ (show i)
-
-runMulSigVector :: (ByteString, ByteString) -> Assertion
-runMulSigVector (a, ops) =
-    assertBool "    >  MultiSig Vector" $ a == b
-  where
-    s = fromRight . decode $ fromJust $ decodeHex ops
-    b = addrToBase58 $ scriptAddr $ fromRight $ decodeOutput s
-
-testSigDecode :: ByteString -> Assertion
-testSigDecode str =
-  let bs = fromJust $ decodeHex str
-      eitherSig = decodeSig bs
-  in
-  assertBool (unwords ["Decode failed:", fromLeft eitherSig]) $ isRight eitherSig
-
-{- Canonical Signatures -}
-
--- Test vectors from bitcoind
--- http://github.com/bitcoin/bitcoin/blob/master/src/test/data/sig_canonical.json
-
-canonicalVectors :: [ByteString]
-canonicalVectors =
-    [ "300602010102010101" -- Changed 0x00 to 0x01 as 0x00 is invalid
-    , "3008020200ff020200ff01"
-    , "304402203932c892e2e550f3af8ee4ce9c215a87f9bb831dcac87b2838e2c2eaa891df0c022030b61dd36543125d56b9f9f3a1f9353189e5af33cdda8d77a5209aec03978fa001"
-    , "30450220076045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba01"
-    , "3046022100876045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba01"
-    ]
-
-notCanonicalVectors :: [ByteString]
-notCanonicalVectors =
-    [ "30050201ff020001"
-    , "30470221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105022200002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-    , "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed11"
-    , "314402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-    , "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-    , "301f01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb101"
-    , "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed0001"
-    , "304401205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-    , "3024020002202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-    , "304402208990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-    , "30450221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-    , "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610501202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-    , "302402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105020001"
-    , "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050220fd5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-    , "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050221002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
-    ]
-
-mulSigVectors :: [(ByteString, ByteString)]
-mulSigVectors =
-    [ ( "3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC"
-      , "52410491bba2510912a5bd37da1fb5b1673010e43d2c6d812c514e91bfa9f2eb129e1c183329db55bd868e209aac2fbc02cb33d98fe74bf23f0c235d6126b1d8334f864104865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac09ef122b1a986818a7cb624532f062c1d1f8722084861c5c3291ccffef4ec687441048d2455d2403e08708fc1f556002f1b6cd83f992d085097f9974ab08a28838f07896fbab08f39495e15fa6fad6edbfb1e754e35fa1c7844c41f322a1863d4621353ae"
-      )
-    ]
-
-scriptSigSignatures :: [ByteString]
-scriptSigSignatures =
-     -- Signature in input of txid 1983a69265920c24f89aac81942b1a59f7eb30821a8b3fb258f88882b6336053
-    [ "304402205ca6249f43538908151fe67b26d020306c0e59fa206cf9f3ccf641f33357119d02206c82f244d04ac0a48024fb9cc246b66e58598acf206139bdb7b75a2941a2b1e401"
-      -- Signature in input of txid fb0a1d8d34fa5537e461ac384bac761125e1bfa7fec286fa72511240fa66864d  Strange DER sizes. But in Blockchain
-    , "3048022200002b83d59c1d23c08efd82ee0662fec23309c3adbcbd1f0b8695378db4b14e736602220000334a96676e58b1bb01784cb7c556dd8ce1c220171904da22e18fe1e7d1510db501"
-    ]
diff --git a/tests/Network/Haskoin/Transaction/Tests.hs b/tests/Network/Haskoin/Transaction/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Transaction/Tests.hs
+++ /dev/null
@@ -1,134 +0,0 @@
-module Network.Haskoin.Transaction.Tests (tests) where
-
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.Serialize (encode)
-import Data.String (fromString)
-import Data.String.Conversions (cs)
-import Data.Word (Word64)
-import qualified Data.ByteString as BS (length)
-
-import Network.Haskoin.Test
-import Network.Haskoin.Transaction
-import Network.Haskoin.Script
-import Network.Haskoin.Crypto
-import Network.Haskoin.Util
-
-tests :: [Test]
-tests =
-    [ testGroup "Transaction tests"
-        [ testProperty "decode . encode Txid" decEncTxid
-        , testProperty "Read/Show transaction id" testReadShowTxHash
-        , testProperty "From string transaction id" testFromStringTxHash
-        ]
-    , testGroup "Building Transactions"
-        [ testProperty "building address tx" testBuildAddrTx
-        , testProperty "testing guessTxSize function" testGuessSize
-        , testProperty "testing chooseCoins function" testChooseCoins
-        , testProperty "testing chooseMSCoins function" testChooseMSCoins
-        ]
-    , testGroup "Signing Transactions"
-        [ testProperty "Sign and validate transactions" testDetSignTx
-        , testProperty "Merge partially signed transactions" testMergeTx
-        ]
-    ]
-
-{- Transaction Tests -}
-
-decEncTxid :: ArbitraryTxHash -> Bool
-decEncTxid (ArbitraryTxHash h) = hexToTxHash (txHashToHex h) == Just h
-
-testReadShowTxHash :: ArbitraryTxHash -> Bool
-testReadShowTxHash (ArbitraryTxHash h) = read (show h) == h
-
-testFromStringTxHash :: ArbitraryTxHash -> Bool
-testFromStringTxHash (ArbitraryTxHash h) = fromString (cs $ txHashToHex h) == h
-
-{- Building Transactions -}
-
-testBuildAddrTx :: ArbitraryAddress -> ArbitrarySatoshi -> Bool
-testBuildAddrTx (ArbitraryAddress a) (ArbitrarySatoshi v) = case a of
-    x@(PubKeyAddress _) -> Right (PayPKHash x) == out
-    x@(ScriptAddress _) -> Right (PayScriptHash x) == out
-  where
-    tx  = buildAddrTx [] [(addrToBase58 a,v)]
-    out = decodeOutputBS $ scriptOutput $ txOut (fromRight tx) !! 0
-
-testGuessSize :: ArbitraryAddrOnlyTx -> Bool
-testGuessSize (ArbitraryAddrOnlyTx tx) =
-    -- We compute an upper bound but it should be close enough to the real size
-    -- We give 2 bytes of slack on every signature (1 on r and 1 on s)
-    guess >= len && guess <= len + 2*delta
-  where
-    delta    = pki + (sum $ map fst msi)
-    guess    = guessTxSize pki msi pkout msout
-    len      = BS.length $ encode tx
-    ins      = map f $ txIn tx
-    f i      = fromRight $ decodeInputBS $ scriptInput i
-    pki      = length $ filter isSpendPKHash ins
-    msi      = concat $ map shData ins
-    shData (ScriptHashInput _ (PayMulSig keys r)) = [(r,length keys)]
-    shData _ = []
-    out      = map (fromRight . decodeOutputBS . scriptOutput) $ txOut tx
-    pkout    = length $ filter isPayPKHash out
-    msout    = length $ filter isPayScriptHash out
-
-testChooseCoins :: Word64 -> Word64 -> [ArbitrarySatoshi] -> Bool
-testChooseCoins target kbfee coins = case chooseCoins target kbfee True coins of
-    Right (chosen, change) ->
-        let outSum = sum $ map coinValue chosen
-            fee    = getFee kbfee (length chosen)
-        in outSum == target + change + fee
-    Left _ ->
-        let fee = getFee kbfee (length coins)
-        in target == 0 || s < target || s < target + fee
-  where
-    s  = sum $ map coinValue coins
-
-testChooseMSCoins :: Word64 -> Word64
-                  -> ArbitraryMSParam -> [ArbitrarySatoshi] -> Bool
-testChooseMSCoins target kbfee (ArbitraryMSParam m n) coins =
-    case chooseMSCoins target kbfee (m,n) True coins of
-        Right (chosen,change) ->
-            let outSum = sum $ map coinValue chosen
-                fee    = getMSFee kbfee (m,n) (length chosen)
-            in outSum == target + change + fee
-        Left _ ->
-            let fee = getMSFee kbfee (m,n) (length coins)
-            in target == 0 || s < target + fee
-  where
-    s  = sum $ map coinValue coins
-
-{- Signing Transactions -}
-
-testDetSignTx :: ArbitrarySigningData -> Bool
-testDetSignTx (ArbitrarySigningData tx sigis prv) =
-    (not $ verifyStdTx tx verData)
-        && (not $ verifyStdTx txSigP verData)
-        && verifyStdTx txSigC verData
-  where
-    txSigP  = fromRight $ signTx tx sigis (tail prv)
-    txSigC  = fromRight $ signTx txSigP sigis [head prv]
-    verData = map (\(SigInput s o _ _) -> (s,o)) sigis
-
-testMergeTx :: ArbitraryPartialTxs -> Bool
-testMergeTx (ArbitraryPartialTxs txs os) = and
-    [ isRight mergeRes
-    , length (txIn mergedTx) == length os
-    , if enoughSigs then isValid else not isValid
-    -- Signature count == min (length txs) (sum required signatures)
-    , sum (map snd sigMap) == min (length txs) (sum (map fst sigMap))
-    ]
-  where
-    outs = map (\(so, op, _, _) -> (so, op)) os
-    mergeRes = mergeTxs txs outs
-    mergedTx = fromRight mergeRes
-    isValid = verifyStdTx mergedTx outs
-    enoughSigs = and $ map (\(m,c) -> c >= m) sigMap
-    sigMap = map (\((_,_,m,_), inp) -> (m, sigCnt inp)) $ zip os $ txIn mergedTx
-    sigCnt inp = case decodeInputBS $ scriptInput inp of
-        Right (RegularInput (SpendMulSig sigs)) -> length sigs
-        Right (ScriptHashInput (SpendMulSig sigs) _) -> length sigs
-        _ -> error "Invalid input script type"
-
diff --git a/tests/Network/Haskoin/Transaction/Units.hs b/tests/Network/Haskoin/Transaction/Units.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Transaction/Units.hs
+++ /dev/null
@@ -1,371 +0,0 @@
-{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}
-module Network.Haskoin.Transaction.Units (tests, satoshiCoreTxTests) where
-
-import Test.HUnit (Assertion, assertBool)
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-
-import Data.Word (Word32, Word64)
-import Data.Maybe (fromJust)
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as BS (reverse)
-import qualified Data.ByteString.Lazy as LBS
-import Data.Serialize (decode, encode, getWord32le, putWord32le, runGet, runPut)
-import Safe (readMay)
-import GHC.Exts( IsString(..) )
-import qualified Data.Aeson as Aeson
-import qualified Data.Aeson.Types as Aeson.Types
-import qualified Data.Vector as V
-import Data.String.Conversions (convertString)
-import Data.List (groupBy)
-import qualified Data.Either
-
-import Network.Haskoin.Transaction
-import Network.Haskoin.Script
-import Network.Haskoin.Util
-
-tests :: [Test]
-tests =
-    [ testGroup "Computing TxID from Tx"
-        ( map mapTxIDVec $ zip txIDVec [0..] )
-    , testGroup "Build PKHash Transaction (generated from bitcoind)"
-        ( map mapPKHashVec $ zip pkHashVec [0..] )
-    , testGroup "Verify transaction (bitcoind /test/data/tx_valid.json)"
-        ( map mapVerifyVec $ zip verifyVec [0..] )
-    , testCase "" tEncodeSatoshiCoreScriptPubKey
-    ]
-
-mapTxIDVec :: ((ByteString, ByteString), Int) -> Test.Framework.Test
-mapTxIDVec (v,i) = testCase name $ runTxIDVec v
-  where
-    name = "Compute TxID " ++ (show i)
-
-runTxIDVec :: (ByteString, ByteString) -> Assertion
-runTxIDVec (tid,tx) = assertBool "TxID" $
-    (txHashToHex $ txHash txBS) == tid
-  where
-    txBS = fromRight . decode $ fromJust $ decodeHex tx
-
-txIDVec :: [(ByteString, ByteString)]
-txIDVec =
-    [ ( "23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"
-      , "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000"
-      )
-    , ( "c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"
-      , "01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000"
-      )
-    , ( "f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"
-      , "01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000"
-      )
-    , ( "afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae"
-      , "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000"
-      )
-    ]
-
-mapPKHashVec :: (([(ByteString, Word32)], [(ByteString, Word64)], ByteString), Int)
-            -> Test.Framework.Test
-mapPKHashVec (v, i) = testCase name $ runPKHashVec v
-    where name = "Build PKHash Tx " ++ (show i)
-
-runPKHashVec :: ([(ByteString, Word32)], [(ByteString, Word64)], ByteString) -> Assertion
-runPKHashVec (xs, ys, res) =
-    assertBool "Build PKHash Tx" $ (encodeHex $ encode tx) == res
-    where tx = fromRight $ buildAddrTx (map f xs) ys
-          f (tid,ix) = OutPoint (fromJust $ hexToTxHash tid) ix
-
-
-mapVerifyVec :: (SatoshiCoreTxTest, Int)
-             -> Test.Framework.Test
-mapVerifyVec (v@(SatoshiCoreTxTest d _ _), i) = testCase name $ runVerifyVec v i
-    where name = "Verify Tx " ++ (show i) ++ ", about: " ++ d
-
-runVerifyVec :: SatoshiCoreTxTest -> Int -> Assertion
-runVerifyVec (SatoshiCoreTxTest _ is bsTx) i =
-    assertBool name $ verifyStdTx tx outputsAndOutpoints
-  where
-    name = "    > Verify transaction " ++ (show i) ++ "bsTx: " ++ convertString bsTx
-    tx :: Tx
-    tx  = fromRight . decode . fromJust . decodeHex $ bsTx
-    outputsAndOutpoints :: [(ScriptOutput, OutPoint)] 
-    outputsAndOutpoints = map f is
-    f (SatoshiCoreTxTestInput bsOutputHash bsOutputIndex bsOutputScriptPubKey) =
-        let s :: ScriptOutput
-            s = either (const $ error $ "could not decode: " ++ convertString bsOutputScriptPubKey) id
-                  . decodeOutputBS . fromJust . decodeHex $ bsOutputScriptPubKey
-            op :: OutPoint
-            op = OutPoint
-                (fromRight . decode . BS.reverse . fromJust . decodeHex $ bsOutputHash)
-                (fromRight . runGet getWord32le  . fromJust . decodeHex $ bsOutputIndex)
-        in (s, op)
-
--- These test vectors have been generated from bitcoind raw transaction api
-
-pkHashVec :: [([(ByteString, Word32)], [(ByteString, Word64)], ByteString)]
-pkHashVec =
-    [
-      ( [("eb29eba154166f6541ebcc9cbdf5088756e026af051f123bcfb526df594549db",14)]
-      , [("14LsRquZfURNFrzpcLVGdaHTfAPjjwiSPb",90000000)]
-      , "0100000001db494559df26b5cf3b121f05af26e0568708f5bd9ccceb41656f1654a1eb29eb0e00000000ffffffff01804a5d05000000001976a91424aa604689cc582292b97668bedd91dd5bf9374c88ac00000000"
-      )
-    , ( [ ("eb29eba154166f6541ebcc9cbdf5088756e026af051f123bcfb526df594549db",0)
-        , ("0001000000000000000000000000000000000000000000000000000000000000",2147483647)
-        ]
-      , [ ("14LsRquZfURNFrzpcLVGdaHTfAPjjwiSPb",1)
-        , ("19VCgS642vzEA1sdByoSn6GsWBwraV8D4n",2100000000000000)
-        ]
-      , "0100000002db494559df26b5cf3b121f05af26e0568708f5bd9ccceb41656f1654a1eb29eb0000000000ffffffff0000000000000000000000000000000000000000000000000000000000000100ffffff7f00ffffffff0201000000000000001976a91424aa604689cc582292b97668bedd91dd5bf9374c88ac0040075af07507001976a9145d16672f53981ff21c5f42b40d1954993cbca54f88ac00000000"
-      )
-    , ( [ ("eb29eba154166f6541ebcc9cbdf5088756e026af051f123bcfb526df594549db",0)
-        , ("0001000000000000000000000000000000000000000000000000000000000000",2147483647)
-        ]
-      , []
-      , "0100000002db494559df26b5cf3b121f05af26e0568708f5bd9ccceb41656f1654a1eb29eb0000000000ffffffff0000000000000000000000000000000000000000000000000000000000000100ffffff7f00ffffffff0000000000"
-      )
-    , ( []
-      , [ ("14LsRquZfURNFrzpcLVGdaHTfAPjjwiSPb",1)
-        , ("19VCgS642vzEA1sdByoSn6GsWBwraV8D4n",2100000000000000)
-        ]
-      , "01000000000201000000000000001976a91424aa604689cc582292b97668bedd91dd5bf9374c88ac0040075af07507001976a9145d16672f53981ff21c5f42b40d1954993cbca54f88ac00000000"
-      )
-    ]
-
-data SatoshiCoreTxTest = SatoshiCoreTxTest String [SatoshiCoreTxTestInput] ByteString
-    deriving (Read,Show)
-
-data SatoshiCoreTxTestInput = SatoshiCoreTxTestInput ByteString ByteString ByteString
-    deriving (Read,Show)
-
-{- Test vectors from bitcoind -}
--- github.com/bitcoin/bitcoin/blob/master/src/test/data/tx_valid.json
--- [[(prevout hash, prevout index, prevout scriptPubKey)], serialized tx],
-verifyVec :: [SatoshiCoreTxTest]
-verifyVec =
-  let toSatCoreTest (is, sertx, description) = SatoshiCoreTxTest description (map toInputs is) sertx
-      toInputs (a,b,c) = SatoshiCoreTxTestInput a b c
-  in  map toSatCoreTest
-    [
-      ( [
-          ( "60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1"
-          , "00000000"
-          , "514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af52ae"
-          )
-        ]
-      , "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000"
-      , "It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"
-      )
-    , ( [
-          ( "60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1"
-          , "00000000"
-          , "514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af52ae"
-          )
-        ]
-      , "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000"
-      , "It has an arbitrary extra byte stuffed into the signature at pos length - 2"
-      )
-    , ( [
-          ( "406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602"
-          , "00000000"
-          , "76a914dc44b1164188067c3a32d4780f5996fa14a4f2d988ac"
-          )
-        ]
-      , "01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000"
-      , "it is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"
-      )
-    , ( [
-          ( "b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d"
-          , "00000000"
-          , "76a914bef80ecf3a44500fda1bc92176e442891662aed288ac"
-          )
-        , ( "b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21"
-          , "01000000"
-          , "76a914bef80ecf3a44500fda1bc92176e442891662aed288ac"
-          )
-        ]
-      , "01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000"
-      , "It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"
-      )
-      
-    , ( [
-          ( "0000000000000000000000000000000000000000000000000000000000000100"
-          , "00000000"
-          , "76a914e52b482f2faa8ecbf0db344f93c84ac908557f3388ac"
-          )
-        , ( "0000000000000000000000000000000000000000000000000000000000000200"
-          , "00000000"
-          , "76a914751e76e8199196d454941c45d1b3a323f1433bd688ac"
-          )
-        ]
-        , "01000000020002000000000000000000000000000000000000000000000000000000000000000000006a47304402200469f169b8091cd18a2770136be7411f079b3ac2b5c199885eb66a80aa3ed75002201fa89f3e6f80974e1b3474e70a0fbe907c766137ff231e4dd05a555d8544536701210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000"
-        , "-- It results in signing the constant 1, instead of something generated based on the transaction,\
-          \-- when the input doing the signing has an index greater than the maximum output index"
-      )
-    , ( [
-          ( "0000000000000000000000000000000000000000000000000000000000000100"
-          , "00000000"
-          , "a9148febbed40483661de6958d957412f82deed8e2f787"
-          )
-        ]
-      , "01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000"
-      , "A valid P2SH Transaction using the standard transaction type put forth in BIP 16"
-      )
-    , ( [
-          ( "0000000000000000000000000000000000000000000000000000000000000100"
-          , "00000000"
-          , "a91432afac281462b822adbec5094b8d4d337dd5bd6a87"
-          )
-        ]
-      , "01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000"
-      , "MAX_MONEY output"
-      )
-    , ( [
-          ( "0000000000000000000000000000000000000000000000000000000000000100"
-          , "00000000"
-          , "a914b558cbf4930954aa6a344363a15668d7477ae71687"
-          )
-        ]
-      , "01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000"
-      , "MAX_MONEY output + 0 output"
-      )
-    , ( [
-          ( "0000000000000000000000000000000000000000000000000000000000000100"
-          , "00000000"
-          , "21035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efcac"
-          )
-        , ( "0000000000000000000000000000000000000000000000000000000000000200"
-          , "00000000"
-          , "21035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efcac"
-          )
-        ]
-      , "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000"
-      , "Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"
-      )
-    , ( [
-          ( "0000000000000000000000000000000000000000000000000000000000000100"
-          , "00000000"
-          , "21035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efcac"
-          )
-        , ( "0000000000000000000000000000000000000000000000000000000000000200"
-          , "00000000"
-          , "21035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efcac"
-          )
-        ]
-      , "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000"
-      , "Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"
-      )
-    , ( [
-          ( "63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70"
-          , "00000000"
-          , "76a914dcf72c4fd02f5a987cf9b02f2fabfcac3341a87d88ac"
-          )
-        , ( "04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d"
-          , "01000000"
-          , "76a914dcf72c4fd02f5a987cf9b02f2fabfcac3341a87d88ac"
-          )
-        , ( "ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f"
-          , "01000000"
-          , "76a914dcf72c4fd02f5a987cf9b02f2fabfcac3341a87d88ac"
-          )
-        ]
-      , "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000"
-      , "several SIGHASH_SINGLE signatures"
-      )
-    ]
-
-tEncodeSatoshiCoreScriptPubKey :: Assertion
-tEncodeSatoshiCoreScriptPubKey = assertBool "tEncodeSatoshiCoreScriptPubKey" $ 
-  t1BsOutputScriptPubKey == encodeSatoshiCoreScriptPubKey t1SatoshiCoreJsonScriptPubKey
-  where 
-    t1BsOutputScriptPubKey :: ByteString
-    t1BsOutputScriptPubKey = "514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af52ae"
-    t1SatoshiCoreJsonScriptPubKey :: String
-    t1SatoshiCoreJsonScriptPubKey = "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"
-
-
-encodeSatoshiCoreScriptPubKey :: String -> ByteString
-encodeSatoshiCoreScriptPubKey = 
-  mconcat . map encodeSatoshiCoreScriptPiece . words
-  where 
-    encodeSatoshiCoreScriptPiece :: String -> ByteString
-    encodeSatoshiCoreScriptPiece s = case (readMay ("OP_" ++ s) :: Maybe ScriptOp) of
-      Just op -> encodeHex . encode $ op
-      Nothing -> case (take 2 s) of 
-          "OP" -> encodeHex . encode . (read :: String -> ScriptOp) $ s
-          "0x" -> ( fromString . drop 2 :: String -> ByteString) $ s          
-          _ -> case (readMay s :: Maybe Int) of -- can we get rid of this case now?
-            Just i -> encodeHex . encode . intToScriptOp $ i
-            Nothing -> error $ "encodeSatoshiCoreScriptPubKey: " ++ s
-
-satoshiCoreTxTests :: IO [Test]
-satoshiCoreTxTests = do
-  txVec <- satoshiCoreTxVec
-  return $ [ 
-    testGroup "Verify transaction (bitcoind /test/data/tx_valid.json) (using copied source json)"
-      ( map mapVerifyVec . filter isCurrentlyPassing $ zip txVec [0..] ) 
-    ]
-  where
-    passingTests = [0..5] ++ [8] ++ [11..13] ++ [16..18] ++ [20] ++ [52]
-    isCurrentlyPassing (_, testNum) = elem testNum passingTests
-
-
-type TestComment = String
-satoshiCoreTxVec :: IO [SatoshiCoreTxTest]
-satoshiCoreTxVec = do 
-    tx_validBS <- LBS.readFile "tests/data/tx_valid.json"
-    let testsAndComments = maybe (error $ "satoshiCoreTxVec, couldn't decode json") id . Aeson.decode $ tx_validBS            
-    return $ case testsAndComments of
-        (Aeson.Array arr) -> 
-            let testsOrComments = map toTestOrComment . V.toList $ arr 
-            in  processTestsAndComments testsOrComments
-        _ -> error $ "satoshiCoreTxVec, testsAndComments not an array"
-      where
-        processTestsAndComments :: [Either TestComment SatoshiCoreTxTest] -> [SatoshiCoreTxTest]
-        processTestsAndComments testOrComments = 
-          -- ghetto parser, because this older version of ootb aeson parser isn't parsec based
-          -- to do ideally soon, upgrade aeson, use aeson/attoparsec, should be much cleaner
-          let grouper = Data.List.groupBy (\x y -> (Data.Either.isLeft x && Data.Either.isLeft y) 
-                                                || (Data.Either.isRight x && Data.Either.isRight y))              
-              takePairs (a:b:xs) = (a,b):takePairs xs
-              takePairs _ = [] -- ugh, wish we were using a real parser.
-              includeDescriptions (descriptionLines,tests') = map updateDescription tests'
-                where updateDescription (Right (SatoshiCoreTxTest _ inputs ser)) = SatoshiCoreTxTest description inputs ser
-                      updateDescription e = error $ "updateDescription: " ++ show e
-                      description = unwords . map fromLeft $ descriptionLines
-          in  concat . map includeDescriptions . takePairs . grouper $ testOrComments
-
-toTestOrComment :: Aeson.Value -> (Either TestComment SatoshiCoreTxTest)
-toTestOrComment testVectorOrComment = 
-  case testVectorOrComment of
-    (Aeson.Types.Array arr) -> 
-      case (V.length arr) of
-        1 ->  let comment = arr V.! 0
-              in case comment of
-                   Aeson.Types.String txt -> Left . convertString $ txt
-                   _ -> error $ "toTestOrComment, comment not text"
-        3 ->  let inputs = case ( arr V.! 0 ) of            
-                    (Aeson.Array inputsV) -> 
-                      let toInput ( Aeson.Array oneInputV ) = 
-                            let hash = case oneInputV V.! 0 of 
-                                  Aeson.String txt -> convertString txt
-                                  _ -> error "processItem, hash not a string"
-                                index = case oneInputV V.! 01 of 
-                                  Aeson.Number n -> encodeHex . runPut . putWord32le . floor $ n
-                                  _ -> error "processItem, n not a number"
-                                pubkey = case oneInputV V.! 2 of
-                                  Aeson.String txt -> encodeSatoshiCoreScriptPubKey . convertString $ txt
-                                  _ -> error "processItem, pubkey not a string"
-                            in  SatoshiCoreTxTestInput hash index pubkey 
-                          toInput _ = error "processItem, oneInputV not an array"
-                      in  map toInput . V.toList $ inputsV
-                    _ -> error "inputs not an array"
-                  tx = let txVal = arr V.! 1
-                       in case txVal of
-                          Aeson.Types.String txt -> convertString txt
-                          _ -> error $ "toTestOrComment, tx, not text"
-                  -- flags -- v V.! 2  -- ignored for now? 
-              in  Right $ SatoshiCoreTxTest "" inputs tx 
-        i -> error $ "toTestOrComment, bad length: " ++ show i 
-    _ -> error "testVectorOrComment is not an array"
-
-
-
-
diff --git a/tests/Network/Haskoin/Util/Tests.hs b/tests/Network/Haskoin/Util/Tests.hs
deleted file mode 100644
--- a/tests/Network/Haskoin/Util/Tests.hs
+++ /dev/null
@@ -1,65 +0,0 @@
-module Network.Haskoin.Util.Tests (tests) where
-
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Data.List (permutations)
-import Data.Maybe (fromJust, catMaybes)
-import Data.Foldable (toList)
-import qualified Data.Sequence as Seq (update, fromList)
-
-import Network.Haskoin.Test
-import Network.Haskoin.Util
-
-tests :: [Test]
-tests =
-    [ testGroup "Utility functions"
-        [ testProperty "bsToInteger . integerToBS" getPutInteger
-        , testProperty "decodeHex . encodeHex" fromToHex
-        , testProperty "compare updateIndex with Data.Sequence" testUpdateIndex
-        , testProperty "matchTemplate" testMatchTemplate
-        , testProperty
-            "testing matchTemplate with two lists" testMatchTemplateLen
-        , testProperty "Testing Either helper functions" testEither
-        ]
-    ]
-
-{- Various utilities -}
-
-getPutInteger :: Integer -> Bool
-getPutInteger i = (bsToInteger $ integerToBS p) == p
-  where
-    p = abs i
-
-fromToHex :: ArbitraryByteString -> Bool
-fromToHex (ArbitraryByteString bs) = (fromJust $ decodeHex $ encodeHex bs) == bs
-
-testUpdateIndex :: [Int] -> Int -> Int -> Bool
-testUpdateIndex xs v i =
-    (updateIndex i xs $ const v) == (toList $ Seq.update i v s)
-  where
-    s = Seq.fromList xs
-
-testMatchTemplate :: [Int] -> Int -> Bool
-testMatchTemplate as i = catMaybes res == bs
-  where
-    res = matchTemplate as bs (==)
-    idx = if length as == 0 then 0 else i `mod` length as
-    bs  = (permutations as) !! idx
-
-testMatchTemplateLen :: [Int] -> [Int] -> Bool
-testMatchTemplateLen as bs = length bs == length res
-  where
-    res = matchTemplate as bs (==)
-
-testEither :: Either String Int -> Bool
-testEither e = case e of
-    (Right v) -> (isRight e)
-              && (not $ isLeft e)
-              && (fromRight e == v)
-              && (eitherToMaybe e == Just v)
-    (Left v)  -> (isLeft e)
-              && (not $ isRight e)
-              && (fromLeft e == v)
-              && (eitherToMaybe e == Nothing)
-
diff --git a/tests/data/script_invalid.json b/tests/data/script_invalid.json
deleted file mode 100644
--- a/tests/data/script_invalid.json
+++ /dev/null
@@ -1,598 +0,0 @@
-[
-["
-Format is: [scriptPubKey, scriptSig, flags, ... comments]
-It is evaluated as if there was a crediting coinbase transaction with two 0
-pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,
-followed by a spending transaction which spends this output as only input (and
-correct prevout hash), using the given scriptSig. All nLockTimes are 0, all
-nSequences are max.
-"],
-
-["", "DEPTH", "P2SH,STRICTENC",   "Test the test: we should have an empty stack after scriptSig evaluation"],
-["  ", "DEPTH", "P2SH,STRICTENC", "and multiple spaces should not change that."],
-["   ", "DEPTH", "P2SH,STRICTENC"],
-["    ", "DEPTH", "P2SH,STRICTENC"],
-
-["", "", "P2SH,STRICTENC"],
-["", "NOP", "P2SH,STRICTENC"],
-["", "NOP DEPTH", "P2SH,STRICTENC"],
-["NOP", "", "P2SH,STRICTENC"],
-["NOP", "DEPTH", "P2SH,STRICTENC"],
-["NOP","NOP", "P2SH,STRICTENC"],
-["NOP","NOP DEPTH", "P2SH,STRICTENC"],
-
-["DEPTH", "", "P2SH,STRICTENC"],
-
-["0x4c01","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA1 with not enough bytes"],
-["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA2 with not enough bytes"],
-["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA4 with not enough bytes"],
-
-["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved"],
-["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "0x51 through 0x60 push 1 through 16 onto stack"],
-["0","NOP", "P2SH,STRICTENC"],
-["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "VER non-functional"],
-["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere"],
-["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere"],
-["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere"],
-["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere"],
-
-["1 IF", "1 ENDIF", "P2SH,STRICTENC", "IF/ENDIF can't span scriptSig/scriptPubKey"],
-["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC"],
-["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC"],
-["0 NOTIF", "123", "P2SH,STRICTENC"],
-
-["0", "DUP IF ENDIF", "P2SH,STRICTENC"],
-["0", "IF 1 ENDIF", "P2SH,STRICTENC"],
-["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC"],
-["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC"],
-["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC"],
-
-["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-
-["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-
-["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "Multiple ELSEs"],
-["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC"],
-
-["1", "ENDIF", "P2SH,STRICTENC", "Malformed IF/ELSE/ENDIF sequence"],
-["1", "ELSE ENDIF", "P2SH,STRICTENC"],
-["1", "ENDIF ELSE", "P2SH,STRICTENC"],
-["1", "ENDIF ELSE IF", "P2SH,STRICTENC"],
-["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC"],
-["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC"],
-["1", "IF ENDIF ENDIF", "P2SH,STRICTENC"],
-["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC"],
-
-["1", "RETURN", "P2SH,STRICTENC"],
-["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC"],
-
-["1", "RETURN 'data'", "P2SH,STRICTENC", "canonical prunable txout format"],
-["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"],
-
-["0", "VERIFY 1", "P2SH,STRICTENC"],
-["1", "VERIFY", "P2SH,STRICTENC"],
-["1", "VERIFY 0", "P2SH,STRICTENC"],
-
-["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "alt stack not shared between sig/pubkey"],
-
-["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"],
-["NOP", "NIP", "P2SH,STRICTENC"],
-["NOP", "1 NIP", "P2SH,STRICTENC"],
-["NOP", "1 0 NIP", "P2SH,STRICTENC"],
-["NOP", "OVER 1", "P2SH,STRICTENC"],
-["1", "OVER", "P2SH,STRICTENC"],
-["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC"],
-["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["NOP", "0 PICK", "P2SH,STRICTENC"],
-["1", "-1 PICK", "P2SH,STRICTENC"],
-["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["NOP", "0 ROLL", "P2SH,STRICTENC"],
-["1", "-1 ROLL", "P2SH,STRICTENC"],
-["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["NOP", "ROT 1", "P2SH,STRICTENC"],
-["NOP", "1 ROT 1", "P2SH,STRICTENC"],
-["NOP", "1 2 ROT 1", "P2SH,STRICTENC"],
-["NOP", "0 1 2 ROT", "P2SH,STRICTENC"],
-["NOP", "SWAP 1", "P2SH,STRICTENC"],
-["1", "SWAP 1", "P2SH,STRICTENC"],
-["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC"],
-["NOP", "TUCK 1", "P2SH,STRICTENC"],
-["1", "TUCK 1", "P2SH,STRICTENC"],
-["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC"],
-["NOP", "2DUP 1", "P2SH,STRICTENC"],
-["1", "2DUP 1", "P2SH,STRICTENC"],
-["NOP", "3DUP 1", "P2SH,STRICTENC"],
-["1", "3DUP 1", "P2SH,STRICTENC"],
-["1 2", "3DUP 1", "P2SH,STRICTENC"],
-["NOP", "2OVER 1", "P2SH,STRICTENC"],
-["1", "2 3 2OVER 1", "P2SH,STRICTENC"],
-["NOP", "2SWAP 1", "P2SH,STRICTENC"],
-["1", "2 3 2SWAP 1", "P2SH,STRICTENC"],
-
-["'a' 'b'", "CAT", "P2SH,STRICTENC", "CAT disabled"],
-["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "CAT disabled"],
-["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "SUBSTR disabled"],
-["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "SUBSTR disabled"],
-["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "LEFT disabled"],
-["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "RIGHT disabled"],
-
-["NOP", "SIZE 1", "P2SH,STRICTENC"],
-
-["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "INVERT disabled"],
-["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "AND disabled"],
-["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "OR disabled"],
-["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "XOR disabled"],
-["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2MUL disabled"],
-["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2DIV disabled"],
-["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MUL disabled"],
-["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DIV disabled"],
-["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MOD disabled"],
-["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "LSHIFT disabled"],
-["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "RSHIFT disabled"],
-
-["0 1","EQUAL", "P2SH,STRICTENC"],
-["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC"],
-["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC"],
-
-["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] "],
-["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] "],
-["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "NUMEQUAL must be in numeric range"],
-["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "NOT is an arithmetic operand"],
-
-["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled"],
-["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
-["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled"],
-["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
-["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
-["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "disabled"],
-["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
-
-["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC"],
-["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC"],
-
-["Ensure 100% coverage of discouraged NOPS"],
-["1", "NOP1",  "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP2",  "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP3",  "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP4",  "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP5",  "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP6",  "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP7",  "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP8",  "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP9",  "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-
-["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig"],
-
-["1 0x01 0xb9", "HASH160 0x14 0x15727299b05b45fdaf9ac9ecf7565cfe27c3e567 EQUAL",
- "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"],
-
-["0x50","1", "P2SH,STRICTENC", "opcode 0x50 is reserved"],
-["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"],
-["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC"],
-
-["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "invalid because scriptSig and scriptPubKey are processed separately"],
-
-["NOP", "RIPEMD160", "P2SH,STRICTENC"],
-["NOP", "SHA1", "P2SH,STRICTENC"],
-["NOP", "SHA256", "P2SH,STRICTENC"],
-["NOP", "HASH160", "P2SH,STRICTENC"],
-["NOP", "HASH256", "P2SH,STRICTENC"],
-
-["NOP",
-"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
-"P2SH,STRICTENC",
-">520 byte push"],
-["0",
-"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1",
-"P2SH,STRICTENC",
-">520 byte push in non-executed IF branch"],
-["1",
-"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
-"P2SH,STRICTENC",
-">201 opcodes executed. 0x61 is NOP"],
-["0",
-"IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1",
-"P2SH,STRICTENC",
-">201 opcodes including non-executed IF branch. 0x61 is NOP"],
-["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"P2SH,STRICTENC",
-">1,000 stack size (0x6f is 3DUP)"],
-["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"P2SH,STRICTENC",
-">1,000 stack+altstack size"],
-["NOP",
-"0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
-"P2SH,STRICTENC",
-"10,001-byte scriptPubKey"],
-
-["NOP1","NOP10", "P2SH,STRICTENC"],
-
-["1","VER", "P2SH,STRICTENC", "OP_VER is reserved"],
-["1","VERIF", "P2SH,STRICTENC", "OP_VERIF is reserved"],
-["1","VERNOTIF", "P2SH,STRICTENC", "OP_VERNOTIF is reserved"],
-["1","RESERVED", "P2SH,STRICTENC", "OP_RESERVED is reserved"],
-["1","RESERVED1", "P2SH,STRICTENC", "OP_RESERVED1 is reserved"],
-["1","RESERVED2", "P2SH,STRICTENC", "OP_RESERVED2 is reserved"],
-["1","0xba", "P2SH,STRICTENC", "0xba == OP_NOP10 + 1"],
-
-["2147483648", "1ADD 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers"],
-["2147483648", "NEGATE 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers"],
-["-2147483648", "1ADD 1", "P2SH,STRICTENC", "Because we use a sign bit, -2147483648 is also 5 bytes"],
-["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
-["2147483648", "1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
-
-["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"],
-["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "We cannot do BOOLAND on 5-byte integers"],
-
-["1", "1 ENDIF", "P2SH,STRICTENC", "ENDIF without IF"],
-["1", "IF 1", "P2SH,STRICTENC", "IF without ENDIF"],
-["1 IF 1", "ENDIF", "P2SH,STRICTENC", "IFs don't carry over"],
-
-["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "The following tests check the if(stack.size() < N) tests in each opcode"],
-["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "They are here to catch copy-and-paste errors"],
-["NOP", "VERIFY 1", "P2SH,STRICTENC", "Most of them are duplicated elsewhere,"],
-
-["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "but, hey, more is always better, right?"],
-["1", "FROMALTSTACK", "P2SH,STRICTENC"],
-["1", "2DROP 1", "P2SH,STRICTENC"],
-["1", "2DUP", "P2SH,STRICTENC"],
-["1 1", "3DUP", "P2SH,STRICTENC"],
-["1 1 1", "2OVER", "P2SH,STRICTENC"],
-["1 1 1 1 1", "2ROT", "P2SH,STRICTENC"],
-["1 1 1", "2SWAP", "P2SH,STRICTENC"],
-["NOP", "IFDUP 1", "P2SH,STRICTENC"],
-["NOP", "DROP 1", "P2SH,STRICTENC"],
-["NOP", "DUP 1", "P2SH,STRICTENC"],
-["1", "NIP", "P2SH,STRICTENC"],
-["1", "OVER", "P2SH,STRICTENC"],
-["1 1 1 3", "PICK", "P2SH,STRICTENC"],
-["0", "PICK 1", "P2SH,STRICTENC"],
-["1 1 1 3", "ROLL", "P2SH,STRICTENC"],
-["0", "ROLL 1", "P2SH,STRICTENC"],
-["1 1", "ROT", "P2SH,STRICTENC"],
-["1", "SWAP", "P2SH,STRICTENC"],
-["1", "TUCK", "P2SH,STRICTENC"],
-
-["NOP", "SIZE 1", "P2SH,STRICTENC"],
-
-["1", "EQUAL 1", "P2SH,STRICTENC"],
-["1", "EQUALVERIFY 1", "P2SH,STRICTENC"],
-
-["NOP", "1ADD 1", "P2SH,STRICTENC"],
-["NOP", "1SUB 1", "P2SH,STRICTENC"],
-["NOP", "NEGATE 1", "P2SH,STRICTENC"],
-["NOP", "ABS 1", "P2SH,STRICTENC"],
-["NOP", "NOT 1", "P2SH,STRICTENC"],
-["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC"],
-
-["1", "ADD", "P2SH,STRICTENC"],
-["1", "SUB", "P2SH,STRICTENC"],
-["1", "BOOLAND", "P2SH,STRICTENC"],
-["1", "BOOLOR", "P2SH,STRICTENC"],
-["1", "NUMEQUAL", "P2SH,STRICTENC"],
-["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"],
-["1", "NUMNOTEQUAL", "P2SH,STRICTENC"],
-["1", "LESSTHAN", "P2SH,STRICTENC"],
-["1", "GREATERTHAN", "P2SH,STRICTENC"],
-["1", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC"],
-["1", "MIN", "P2SH,STRICTENC"],
-["1", "MAX", "P2SH,STRICTENC"],
-["1 1", "WITHIN", "P2SH,STRICTENC"],
-
-["NOP", "RIPEMD160 1", "P2SH,STRICTENC"],
-["NOP", "SHA1 1", "P2SH,STRICTENC"],
-["NOP", "SHA256 1", "P2SH,STRICTENC"],
-["NOP", "HASH160 1", "P2SH,STRICTENC"],
-["NOP", "HASH256 1", "P2SH,STRICTENC"],
-
-["",
-"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG",
-"P2SH,STRICTENC",
-"202 CHECKMULTISIGS, fails due to 201 op limit"],
-
-["1",
-"0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY",
-"P2SH,STRICTENC"],
-
-["",
-"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG",
-"P2SH,STRICTENC",
-"Fails due to 201 sig op limit"],
-
-["1",
-"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY",
-"P2SH,STRICTENC"],
-
-
-["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "nPubKeys > 20"],
-["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "nSigs > nPubKeys"],
-
-
-["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "Tests for Script.IsPushOnly()"],
-["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC"],
-
-["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "OP_RESERVED in P2SH should fail"],
-["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "OP_VER in P2SH should fail"],
-
-["0x00", "'00' EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"],
-
-["MINIMALDATA enforcement for PUSHDATAs"],
-
-["0x4c 0x00", "DROP 1", "MINIMALDATA", "Empty vector minimally represented by OP_0"],
-["0x01 0x81", "DROP 1", "MINIMALDATA", "-1 minimally represented by OP_1NEGATE"],
-["0x01 0x01", "DROP 1", "MINIMALDATA", "1 to 16 minimally represented by OP_1 to OP_16"],
-["0x01 0x02", "DROP 1", "MINIMALDATA"],
-["0x01 0x03", "DROP 1", "MINIMALDATA"],
-["0x01 0x04", "DROP 1", "MINIMALDATA"],
-["0x01 0x05", "DROP 1", "MINIMALDATA"],
-["0x01 0x06", "DROP 1", "MINIMALDATA"],
-["0x01 0x07", "DROP 1", "MINIMALDATA"],
-["0x01 0x08", "DROP 1", "MINIMALDATA"],
-["0x01 0x09", "DROP 1", "MINIMALDATA"],
-["0x01 0x0a", "DROP 1", "MINIMALDATA"],
-["0x01 0x0b", "DROP 1", "MINIMALDATA"],
-["0x01 0x0c", "DROP 1", "MINIMALDATA"],
-["0x01 0x0d", "DROP 1", "MINIMALDATA"],
-["0x01 0x0e", "DROP 1", "MINIMALDATA"],
-["0x01 0x0f", "DROP 1", "MINIMALDATA"],
-["0x01 0x10", "DROP 1", "MINIMALDATA"],
-
-["0x4c 0x48 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
- "PUSHDATA1 of 72 bytes minimally represented by direct push"],
-
-["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
- "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1"],
-
-["0x4f 0x00100000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
- "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2"],
-
-
-["MINIMALDATA enforcement for numeric arguments"],
-
-["0x01 0x00", "NOT DROP 1", "MINIMALDATA", "numequals 0"],
-["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "numequals 0"],
-["0x01 0x80", "NOT DROP 1", "MINIMALDATA", "0x80 (negative zero) numequals 0"],
-["0x02 0x0080", "NOT DROP 1", "MINIMALDATA", "numequals 0"],
-["0x02 0x0500", "NOT DROP 1", "MINIMALDATA", "numequals 5"],
-["0x03 0x050000", "NOT DROP 1", "MINIMALDATA", "numequals 5"],
-["0x02 0x0580", "NOT DROP 1", "MINIMALDATA", "numequals -5"],
-["0x03 0x050080", "NOT DROP 1", "MINIMALDATA", "numequals -5"],
-["0x03 0xff7f80", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffff"],
-["0x03 0xff7f00", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xff7f"],
-["0x04 0xffff7f80", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffffff"],
-["0x04 0xffff7f00", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffff7f"],
-
-["Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule"],
-
-["1 0x02 0x0000", "PICK DROP", "MINIMALDATA"],
-["1 0x02 0x0000", "ROLL DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "1ADD DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "1SUB DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "NEGATE DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "ABS DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "NOT DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "0NOTEQUAL DROP 1", "MINIMALDATA"],
-
-["0 0x02 0x0000", "ADD DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "ADD DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "SUB DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "SUB DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "BOOLAND DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "BOOLAND DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "BOOLOR DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "BOOLOR DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "NUMEQUAL DROP 1", "MINIMALDATA"],
-["0x02 0x0000 1", "NUMEQUAL DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "NUMEQUALVERIFY 1", "MINIMALDATA"],
-["0x02 0x0000 0", "NUMEQUALVERIFY 1", "MINIMALDATA"],
-["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "LESSTHAN DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "LESSTHAN DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "GREATERTHAN DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "GREATERTHAN DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "MIN DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "MIN DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "MAX DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "MAX DROP 1", "MINIMALDATA"],
-
-["0x02 0x0000 0 0", "WITHIN DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000 0", "WITHIN DROP 1", "MINIMALDATA"],
-["0 0 0x02 0x0000", "WITHIN DROP 1", "MINIMALDATA"],
-
-["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "MINIMALDATA"],
-["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "MINIMALDATA"],
-["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA"],
-
-
-[
-    "0x47 0x30440220304eff7556bba9560df47873275e64db45f3cd735998ce3f00d2e57b1bb5f31302205c0c9d14b8b80d43e2ac9b87532f1af6d8a3271262bc694ec4e14068392bb0a001",
-    "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
-    "",
-    "P2PK, bad sig"
-],
-[
-    "0x47 0x3044022037fcdb8e08f41e27588de8bc036d2c4b16eb3d09c1ba53b8f47a0a9c27722a39022058664b7a53b507e71dfafb77193e3786c3f0c119d78ce9104480ee7ece04f09301 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
-    "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG",
-    "",
-    "P2PKH, bad pubkey"
-],
-[
-    "0x47 0x3044022035e5b6742d299861c84cebaf2ea64145ee427a95facab39e2594d6deebb0c1d602200acb16778faa2e467a59006f342f2535b1418d55ba63a8605b387b7f9ac86d9a01",
-    "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
-    "",
-    "P2PK anyonecanpay marked with normal hashtype"
-],
-[
-    "0x47 0x3044022029b2b8765ca950cf75a69e80b73b7ddfcaa8b27080c2db4c23b36aae60688e790220598ff368e17872ee065aa54d7d3a590682ca5204325b23b31d7da3c4a21ae67901 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
-    "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
-    "P2SH",
-    "P2SH(P2PK), bad redeemscript"
-],
-[
-    "0x47 0x30440220647f906e63890df5ef1d3fed47ba892b31976c634281079e2bd38504fb54a1fb022021e8811f38fbe90efb6b74cb78da01d9badbac3bafdf70a861d7538a220d0b2601 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
-    "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
-    "P2SH",
-    "P2SH(P2PKH), bad sig"
-],
-[
-    "0 0x47 0x304402203ef170402f8887f2ac183f31b1f503b0bc60bfc968dd469b097ea6124aefac5002200612febadc4e4cacc086982cb85830a17af3680c1b6a3cf77c1708af7621cf1301 0 0x47 0x304402207821838251a24a2234844f68e7169e6d11945cdf052ea12bd3e4e37457aceb4402200b6b46c81361e314c740ae5133c072af5fa5c209d65d2db1679e1716f19a538101",
-    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
-    "",
-    "3-of-3, 2 sigs"
-],
-[
-    "0 0 0x47 0x304402204661f7795e8db7be3132e8974e9a76d1d24b31f23df94c6fbcea07d1c205789102203f5e45a1c0b085279b58d11b36d5fea5449c3cf16f844ad10124e9b65e8777d201 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
-    "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
-    "P2SH",
-    "P2SH(2-of-3), 1 sig"
-],
-[
-    "0x47 0x30440220005d727e2a82d6e8a98a6da6fbc281325644d1a40455e386fdb17883a8e6bc4d02202d15cca42ce136047a980d288e60c679d7e84cce18c3ceffb6bc81b9e9ba517801",
-    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
-    "",
-    "P2PK NOT with too much R padding but no DERSIG"
-],
-[
-    "0x47 0x30440220006e8bc4f82032b12bd594847c16d8b2986de734aa3b0528bd89d664d41e6d1c02200cfd582694891bcfa2e630e899bda257486eba00a007222fae71144dba07dc2901",
-    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
-    "DERSIG",
-    "P2PK NOT with too much R padding"
-],
-[
-    "0x47 0x304402203aab50cd7c30cc1e1475dee615b295bcee6ccf8aa8a7f6cda6b696c70d79cbb40220558e43fe7596c31146e2d077698d5a9c38351d8ba567549a2ae43ca97231c39501",
-    "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
-    "STRICTENC",
-    "P2PK with hybrid pubkey"
-],
-
-["
-Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of
-pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded
-signatures and pubkeys.
-"],
-
-[
-    "0x01 0x01 0x47 0x304402200e48ba1cf4d7182db94ffb57bd72ea31b5545dc0d1c512e665779b4fb2badc52022054b8388dfc074c708a75b62359b7be46402751ee40c0a111aef38a837b6ed09801 0x47 0x304402201c9820f59c49107bb30e6175cfc9ec95f897b03beb628b4bc854d2b80392aa0602200235d986ae418bcd111b8814f4c26a0ab5f475fb542a44884fc14912a97a252301 0x47 0x304402204cd7894c6f10a871f5b0c1f9c13228f8cdd4050248f0d0f498ee86be69ee3080022051bd2932c7d585eb600c7194235c74da820935f0d67972fd9545673aa1fd023301",
-    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
-    "NULLDUMMY",
-    "3-of-3 with nonzero dummy"
-],
-[
-    "0x01 0x01 0x47 0x304402201847fc3b8f7597768e7f543c58da1fca6e8e35eb28979431e6b637572ce6eaa4022048dd58608e040841d0bf52a70cfb70e1a9c8d2826fad068f4e9d2bf5c87766a501 0x47 0x30440220711311a72516affed73363763983d05c3d6a06a2eadf5d76b90b4354162ba94302204841a69e5955a7dc8e4ab3105fd0c86040c1dac6016297a51ddbf5079c28756801 0x47 0x30440220267e331a378191e7282fd10d61c97bf74bc97c233c5833d677936424ac08dee502201eee83d88b91988e1c4d9b979df2404aa190e0987a8ca09c4e5cd61da1d48ecc01",
-    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
-    "NULLDUMMY",
-    "3-of-3 NOT with invalid sig with nonzero dummy"
-],
-[
-    "0 0x47 0x3044022035341cc377b19138f944f90c45772cb06338c6d56a4c0c31a65bf1a8a105fadc022046dd232850b6bacb25879c9da82a7a628982aa19d055f1753468f68047662e0301 DUP",
-    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
-    "SIGPUSHONLY",
-    "2-of-2 with two identical keys and sigs pushed using OP_DUP"
-],
-[
-    "0x47 0x304402204d8b99eea2f53382fd67e0dbc8ed0596bd614aa0dad6bc6843c7860c79b901c3022062f022a71993013e3d9b22302a8e4b40109d7bb057aeb250b9aab2197b3e96b801 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
-    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
-    "",
-    "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY"
-],
-[
-    "0x47 0x30440220078c887c33abc67fbbd827ceb3f661c1c459e78218161b652f23e3ca76cfabbd022047df245eacb8a88d8c5ca7b5228e3b4d070c102d2f542433362d3f443cd24eda01 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
-    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
-    "SIGPUSHONLY",
-    "P2SH(P2PK) with non-push scriptSig"
-],
-
-["The End"]
-]
diff --git a/tests/data/script_valid.json b/tests/data/script_valid.json
deleted file mode 100644
--- a/tests/data/script_valid.json
+++ /dev/null
@@ -1,821 +0,0 @@
-[
-["
-Format is: [scriptPubKey, scriptSig, flags, ... comments]
-It is evaluated as if there was a crediting coinbase transaction with two 0
-pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,
-followed by a spending transaction which spends this output as only input (and
-correct prevout hash), using the given scriptSig. All nLockTimes are 0, all
-nSequences are max.
-"],
-
-["", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation"],
-["  ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "and multiple spaces should not change that."],
-["   ", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["    ", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "Similarly whitespace around and between symbols"],
-["1  2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"],
-["  1  2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"],
-["1  2  ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"],
-["  1  2  ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"],
-
-["1", "", "P2SH,STRICTENC"],
-["0x02 0x01 0x00", "", "P2SH,STRICTENC", "all bytes are significant, not only the last one"],
-["0x09 0x00000000 0x00000000 0x10", "", "P2SH,STRICTENC", "equals zero when cast to Int64"],
-
-["0x01 0x0b", "11 EQUAL", "P2SH,STRICTENC", "push 1 byte"],
-["0x02 0x417a", "'Az' EQUAL", "P2SH,STRICTENC"],
-["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a",
- "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "P2SH,STRICTENC", "push 75 bytes"],
-
-["0x4c 0x01 0x07","7 EQUAL", "P2SH,STRICTENC", "0x4c is OP_PUSHDATA1"],
-["0x4d 0x0100 0x08","8 EQUAL", "P2SH,STRICTENC", "0x4d is OP_PUSHDATA2"],
-["0x4e 0x01000000 0x09","9 EQUAL", "P2SH,STRICTENC", "0x4e is OP_PUSHDATA4"],
-
-["0x4c 0x00","0 EQUAL", "P2SH,STRICTENC"],
-["0x4d 0x0000","0 EQUAL", "P2SH,STRICTENC"],
-["0x4e 0x00000000","0 EQUAL", "P2SH,STRICTENC"],
-["0x4f 1000 ADD","999 EQUAL", "P2SH,STRICTENC"],
-["0", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved (ok if not executed)"],
-["0x51", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "0x51 through 0x60 push 1 through 16 onto stack"],
-["1","NOP", "P2SH,STRICTENC"],
-["0", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "VER non-functional (ok if not executed)"],
-["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "P2SH,STRICTENC", "RESERVED ok in un-executed IF"],
-
-["1", "DUP IF ENDIF", "P2SH,STRICTENC"],
-["1", "IF 1 ENDIF", "P2SH,STRICTENC"],
-["1", "DUP IF ELSE ENDIF", "P2SH,STRICTENC"],
-["1", "IF 1 ELSE ENDIF", "P2SH,STRICTENC"],
-["0", "IF ELSE 1 ENDIF", "P2SH,STRICTENC"],
-
-["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-
-["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-
-["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"],
-["1", "IF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC"],
-["1", "IF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"],
-["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC"],
-
-["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"],
-["0", "NOTIF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC"],
-["0", "NOTIF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"],
-["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC"],
-
-["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "Nested ELSE ELSE"],
-["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"],
-
-["0", "IF RETURN ENDIF 1", "P2SH,STRICTENC", "RETURN only works if executed"],
-
-["1 1", "VERIFY", "P2SH,STRICTENC"],
-["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "P2SH,STRICTENC", "values >4 bytes can be cast to boolean"],
-
-["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL", "P2SH,STRICTENC"],
-["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL", "P2SH,STRICTENC"],
-
-["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"],
-["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"],
-["0 DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"],
-["0 1", "NIP", "P2SH,STRICTENC"],
-["1 0", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC"],
-["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "ROT 22 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "ROT DROP 20 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "ROT DROP DROP 21 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "ROT ROT 21 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "ROT ROT ROT 20 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 24 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT DROP 25 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL", "P2SH,STRICTENC"],
-["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"],
-["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC"],
-["13 14", "2DUP ROT EQUALVERIFY EQUAL", "P2SH,STRICTENC"],
-["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY", "P2SH,STRICTENC"],
-["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL", "P2SH,STRICTENC"],
-["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL", "P2SH,STRICTENC"],
-["0", "SIZE 0 EQUAL", "P2SH,STRICTENC"],
-["1", "SIZE 1 EQUAL", "P2SH,STRICTENC"],
-["127", "SIZE 1 EQUAL", "P2SH,STRICTENC"],
-["128", "SIZE 2 EQUAL", "P2SH,STRICTENC"],
-["32767", "SIZE 2 EQUAL", "P2SH,STRICTENC"],
-["32768", "SIZE 3 EQUAL", "P2SH,STRICTENC"],
-["8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC"],
-["8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC"],
-["2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC"],
-["2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC"],
-["549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC"],
-["549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC"],
-["9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC"],
-["-1", "SIZE 1 EQUAL", "P2SH,STRICTENC"],
-["-127", "SIZE 1 EQUAL", "P2SH,STRICTENC"],
-["-128", "SIZE 2 EQUAL", "P2SH,STRICTENC"],
-["-32767", "SIZE 2 EQUAL", "P2SH,STRICTENC"],
-["-32768", "SIZE 3 EQUAL", "P2SH,STRICTENC"],
-["-8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC"],
-["-8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC"],
-["-2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC"],
-["-2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC"],
-["-549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC"],
-["-549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC"],
-["-9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL", "P2SH,STRICTENC"],
-
-["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "P2SH,STRICTENC", "SIZE does not consume argument"],
-
-["2 -2 ADD", "0 EQUAL", "P2SH,STRICTENC"],
-["2147483647 -2147483647 ADD", "0 EQUAL", "P2SH,STRICTENC"],
-["-1 -1 ADD", "-2 EQUAL", "P2SH,STRICTENC"],
-
-["0 0","EQUAL", "P2SH,STRICTENC"],
-["1 1 ADD", "2 EQUAL", "P2SH,STRICTENC"],
-["1 1ADD", "2 EQUAL", "P2SH,STRICTENC"],
-["111 1SUB", "110 EQUAL", "P2SH,STRICTENC"],
-["111 1 ADD 12 SUB", "100 EQUAL", "P2SH,STRICTENC"],
-["0 ABS", "0 EQUAL", "P2SH,STRICTENC"],
-["16 ABS", "16 EQUAL", "P2SH,STRICTENC"],
-["-16 ABS", "-16 NEGATE EQUAL", "P2SH,STRICTENC"],
-["0 NOT", "NOP", "P2SH,STRICTENC"],
-["1 NOT", "0 EQUAL", "P2SH,STRICTENC"],
-["11 NOT", "0 EQUAL", "P2SH,STRICTENC"],
-["0 0NOTEQUAL", "0 EQUAL", "P2SH,STRICTENC"],
-["1 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"],
-["111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"],
-["-111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"],
-["1 1 BOOLAND", "NOP", "P2SH,STRICTENC"],
-["1 0 BOOLAND", "NOT", "P2SH,STRICTENC"],
-["0 1 BOOLAND", "NOT", "P2SH,STRICTENC"],
-["0 0 BOOLAND", "NOT", "P2SH,STRICTENC"],
-["16 17 BOOLAND", "NOP", "P2SH,STRICTENC"],
-["1 1 BOOLOR", "NOP", "P2SH,STRICTENC"],
-["1 0 BOOLOR", "NOP", "P2SH,STRICTENC"],
-["0 1 BOOLOR", "NOP", "P2SH,STRICTENC"],
-["0 0 BOOLOR", "NOT", "P2SH,STRICTENC"],
-["16 17 BOOLOR", "NOP", "P2SH,STRICTENC"],
-["11 10 1 ADD", "NUMEQUAL", "P2SH,STRICTENC"],
-["11 10 1 ADD", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"],
-["11 10 1 ADD", "NUMNOTEQUAL NOT", "P2SH,STRICTENC"],
-["111 10 1 ADD", "NUMNOTEQUAL", "P2SH,STRICTENC"],
-["11 10", "LESSTHAN NOT", "P2SH,STRICTENC"],
-["4 4", "LESSTHAN NOT", "P2SH,STRICTENC"],
-["10 11", "LESSTHAN", "P2SH,STRICTENC"],
-["-11 11", "LESSTHAN", "P2SH,STRICTENC"],
-["-11 -10", "LESSTHAN", "P2SH,STRICTENC"],
-["11 10", "GREATERTHAN", "P2SH,STRICTENC"],
-["4 4", "GREATERTHAN NOT", "P2SH,STRICTENC"],
-["10 11", "GREATERTHAN NOT", "P2SH,STRICTENC"],
-["-11 11", "GREATERTHAN NOT", "P2SH,STRICTENC"],
-["-11 -10", "GREATERTHAN NOT", "P2SH,STRICTENC"],
-["11 10", "LESSTHANOREQUAL NOT", "P2SH,STRICTENC"],
-["4 4", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["10 11", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["-11 11", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["-11 -10", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["11 10", "GREATERTHANOREQUAL", "P2SH,STRICTENC"],
-["4 4", "GREATERTHANOREQUAL", "P2SH,STRICTENC"],
-["10 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"],
-["-11 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"],
-["-11 -10", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"],
-["1 0 MIN", "0 NUMEQUAL", "P2SH,STRICTENC"],
-["0 1 MIN", "0 NUMEQUAL", "P2SH,STRICTENC"],
-["-1 0 MIN", "-1 NUMEQUAL", "P2SH,STRICTENC"],
-["0 -2147483647 MIN", "-2147483647 NUMEQUAL", "P2SH,STRICTENC"],
-["2147483647 0 MAX", "2147483647 NUMEQUAL", "P2SH,STRICTENC"],
-["0 100 MAX", "100 NUMEQUAL", "P2SH,STRICTENC"],
-["-100 0 MAX", "0 NUMEQUAL", "P2SH,STRICTENC"],
-["0 -2147483647 MAX", "0 NUMEQUAL", "P2SH,STRICTENC"],
-["0 0 1", "WITHIN", "P2SH,STRICTENC"],
-["1 0 1", "WITHIN NOT", "P2SH,STRICTENC"],
-["0 -2147483647 2147483647", "WITHIN", "P2SH,STRICTENC"],
-["-1 -100 100", "WITHIN", "P2SH,STRICTENC"],
-["11 -100 100", "WITHIN", "P2SH,STRICTENC"],
-["-2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC"],
-["2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC"],
-
-["2147483647 2147483647 SUB", "0 EQUAL", "P2SH,STRICTENC"],
-["2147483647 DUP ADD", "4294967294 EQUAL", "P2SH,STRICTENC", ">32 bit EQUAL is valid"],
-["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL", "P2SH,STRICTENC"],
-
-["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL", "P2SH,STRICTENC"],
-["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL", "P2SH,STRICTENC"],
-["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL", "P2SH,STRICTENC"],
-["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL", "P2SH,STRICTENC"],
-["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL", "P2SH,STRICTENC"],
-["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL", "P2SH,STRICTENC"],
-["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL", "P2SH,STRICTENC"],
-["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL", "P2SH,STRICTENC"],
-["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL", "P2SH,STRICTENC"],
-["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL", "P2SH,STRICTENC"],
-["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL", "P2SH,STRICTENC"],
-["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC"],
-
-
-["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC"],
-["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC"],
-
-["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "Discourage NOPx flag allows OP_NOP"],
-
-["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS",
- "Discouraged NOPs are allowed if not executed"],
-
-["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"],
-["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC"],
-
-["NOP",
-"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
-"P2SH,STRICTENC",
-"520 byte push"],
-["1",
-"0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
-"P2SH,STRICTENC",
-"201 opcodes executed. 0x61 is NOP"],
-["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"P2SH,STRICTENC",
-"1,000 stack size (0x6f is 3DUP)"],
-["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"P2SH,STRICTENC",
-"1,000 stack size (altstack cleared between scriptSig/scriptPubKey)"],
-["'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
-"P2SH,STRICTENC",
-"Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"],
-
-["0",
-"IF 0x5050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 ENDIF 1",
-"P2SH,STRICTENC",
-">201 opcodes, but RESERVED (0x50) doesn't count towards opcode limit."],
-
-["NOP","1", "P2SH,STRICTENC"],
-
-["1", "0x01 0x01 EQUAL", "P2SH,STRICTENC", "The following is useful for checking implementations of BN_bn2mpi"],
-["127", "0x01 0x7F EQUAL", "P2SH,STRICTENC"],
-["128", "0x02 0x8000 EQUAL", "P2SH,STRICTENC", "Leave room for the sign bit"],
-["32767", "0x02 0xFF7F EQUAL", "P2SH,STRICTENC"],
-["32768", "0x03 0x008000 EQUAL", "P2SH,STRICTENC"],
-["8388607", "0x03 0xFFFF7F EQUAL", "P2SH,STRICTENC"],
-["8388608", "0x04 0x00008000 EQUAL", "P2SH,STRICTENC"],
-["2147483647", "0x04 0xFFFFFF7F EQUAL", "P2SH,STRICTENC"],
-["2147483648", "0x05 0x0000008000 EQUAL", "P2SH,STRICTENC"],
-["549755813887", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC"],
-["549755813888", "0x06 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC"],
-["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC"],
-["-1", "0x01 0x81 EQUAL", "P2SH,STRICTENC", "Numbers are little-endian with the MSB being a sign bit"],
-["-127", "0x01 0xFF EQUAL", "P2SH,STRICTENC"],
-["-128", "0x02 0x8080 EQUAL", "P2SH,STRICTENC"],
-["-32767", "0x02 0xFFFF EQUAL", "P2SH,STRICTENC"],
-["-32768", "0x03 0x008080 EQUAL", "P2SH,STRICTENC"],
-["-8388607", "0x03 0xFFFFFF EQUAL", "P2SH,STRICTENC"],
-["-8388608", "0x04 0x00008080 EQUAL", "P2SH,STRICTENC"],
-["-2147483647", "0x04 0xFFFFFFFF EQUAL", "P2SH,STRICTENC"],
-["-2147483648", "0x05 0x0000008080 EQUAL", "P2SH,STRICTENC"],
-["-4294967295", "0x05 0xFFFFFFFF80 EQUAL", "P2SH,STRICTENC"],
-["-549755813887", "0x05 0xFFFFFFFFFF EQUAL", "P2SH,STRICTENC"],
-["-549755813888", "0x06 0x000000008080 EQUAL", "P2SH,STRICTENC"],
-["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL", "P2SH,STRICTENC"],
-
-["2147483647", "1ADD 2147483648 EQUAL", "P2SH,STRICTENC", "We can do math on 4-byte integers, and compare 5-byte ones"],
-["2147483647", "1ADD 1", "P2SH,STRICTENC"],
-["-2147483647", "1ADD 1", "P2SH,STRICTENC"],
-
-["1", "0x02 0x0100 EQUAL NOT", "P2SH,STRICTENC", "Not the same byte array..."],
-["1", "0x02 0x0100 NUMEQUAL", "P2SH,STRICTENC", "... but they are numerically equal"],
-["11", "0x4c 0x03 0x0b0000 NUMEQUAL", "P2SH,STRICTENC"],
-["0", "0x01 0x80 EQUAL NOT", "P2SH,STRICTENC"],
-["0", "0x01 0x80 NUMEQUAL", "P2SH,STRICTENC", "Zero numerically equals negative zero"],
-["0", "0x02 0x0080 NUMEQUAL", "P2SH,STRICTENC"],
-["0x03 0x000080", "0x04 0x00000080 NUMEQUAL", "P2SH,STRICTENC"],
-["0x03 0x100080", "0x04 0x10000080 NUMEQUAL", "P2SH,STRICTENC"],
-["0x03 0x100000", "0x04 0x10000000 NUMEQUAL", "P2SH,STRICTENC"],
-
-["NOP", "NOP 1", "P2SH,STRICTENC", "The following tests check the if(stack.size() < N) tests in each opcode"],
-["1", "IF 1 ENDIF", "P2SH,STRICTENC", "They are here to catch copy-and-paste errors"],
-["0", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "Most of them are duplicated elsewhere,"],
-["1", "VERIFY 1", "P2SH,STRICTENC", "but, hey, more is always better, right?"],
-
-["0", "TOALTSTACK 1", "P2SH,STRICTENC"],
-["1", "TOALTSTACK FROMALTSTACK", "P2SH,STRICTENC"],
-["0 0", "2DROP 1", "P2SH,STRICTENC"],
-["0 1", "2DUP", "P2SH,STRICTENC"],
-["0 0 1", "3DUP", "P2SH,STRICTENC"],
-["0 1 0 0", "2OVER", "P2SH,STRICTENC"],
-["0 1 0 0 0 0", "2ROT", "P2SH,STRICTENC"],
-["0 1 0 0", "2SWAP", "P2SH,STRICTENC"],
-["1", "IFDUP", "P2SH,STRICTENC"],
-["NOP", "DEPTH 1", "P2SH,STRICTENC"],
-["0", "DROP 1", "P2SH,STRICTENC"],
-["1", "DUP", "P2SH,STRICTENC"],
-["0 1", "NIP", "P2SH,STRICTENC"],
-["1 0", "OVER", "P2SH,STRICTENC"],
-["1 0 0 0 3", "PICK", "P2SH,STRICTENC"],
-["1 0", "PICK", "P2SH,STRICTENC"],
-["1 0 0 0 3", "ROLL", "P2SH,STRICTENC"],
-["1 0", "ROLL", "P2SH,STRICTENC"],
-["1 0 0", "ROT", "P2SH,STRICTENC"],
-["1 0", "SWAP", "P2SH,STRICTENC"],
-["0 1", "TUCK", "P2SH,STRICTENC"],
-
-["1", "SIZE", "P2SH,STRICTENC"],
-
-["0 0", "EQUAL", "P2SH,STRICTENC"],
-["0 0", "EQUALVERIFY 1", "P2SH,STRICTENC"],
-
-["0", "1ADD", "P2SH,STRICTENC"],
-["2", "1SUB", "P2SH,STRICTENC"],
-["-1", "NEGATE", "P2SH,STRICTENC"],
-["-1", "ABS", "P2SH,STRICTENC"],
-["0", "NOT", "P2SH,STRICTENC"],
-["-1", "0NOTEQUAL", "P2SH,STRICTENC"],
-
-["1 0", "ADD", "P2SH,STRICTENC"],
-["1 0", "SUB", "P2SH,STRICTENC"],
-["-1 -1", "BOOLAND", "P2SH,STRICTENC"],
-["-1 0", "BOOLOR", "P2SH,STRICTENC"],
-["0 0", "NUMEQUAL", "P2SH,STRICTENC"],
-["0 0", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"],
-["-1 0", "NUMNOTEQUAL", "P2SH,STRICTENC"],
-["-1 0", "LESSTHAN", "P2SH,STRICTENC"],
-["1 0", "GREATERTHAN", "P2SH,STRICTENC"],
-["0 0", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["0 0", "GREATERTHANOREQUAL", "P2SH,STRICTENC"],
-["-1 0", "MIN", "P2SH,STRICTENC"],
-["1 0", "MAX", "P2SH,STRICTENC"],
-["-1 -1 0", "WITHIN", "P2SH,STRICTENC"],
-
-["0", "RIPEMD160", "P2SH,STRICTENC"],
-["0", "SHA1", "P2SH,STRICTENC"],
-["0", "SHA256", "P2SH,STRICTENC"],
-["0", "HASH160", "P2SH,STRICTENC"],
-["0", "HASH256", "P2SH,STRICTENC"],
-["NOP", "CODESEPARATOR 1", "P2SH,STRICTENC"],
-
-["NOP", "NOP1 1", "P2SH,STRICTENC"],
-["NOP", "NOP2 1", "P2SH,STRICTENC"],
-["NOP", "NOP3 1", "P2SH,STRICTENC"],
-["NOP", "NOP4 1", "P2SH,STRICTENC"],
-["NOP", "NOP5 1", "P2SH,STRICTENC"],
-["NOP", "NOP6 1", "P2SH,STRICTENC"],
-["NOP", "NOP7 1", "P2SH,STRICTENC"],
-["NOP", "NOP8 1", "P2SH,STRICTENC"],
-["NOP", "NOP9 1", "P2SH,STRICTENC"],
-["NOP", "NOP10 1", "P2SH,STRICTENC"],
-
-["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "CHECKMULTISIG is allowed to have zero keys and/or sigs"],
-["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Zero sigs means no sigs are checked"],
-["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-
-["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "CHECKMULTISIG is allowed to have zero keys and/or sigs"],
-["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Zero sigs means no sigs are checked"],
-["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-
-["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Test from up to 20 pubkeys, all not checked"],
-["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-
-["",
-"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG",
-"P2SH,STRICTENC",
-"nOpCount is incremented by the number of keys evaluated in addition to the usual one op per op. In this case we have zero keys, so we can execute 201 CHECKMULTISIGS"],
-
-["1",
-"0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY",
-"P2SH,STRICTENC"],
-
-["",
-"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG",
-"P2SH,STRICTENC",
-"Even though there are no signatures being checked nOpCount is incremented by the number of keys."],
-
-["1",
-"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY",
-"P2SH,STRICTENC"],
-
-["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "Very basic P2SH"],
-["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC"],
-
-["0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
-"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL",
-"P2SH,STRICTENC",
-"Basic PUSH signedness check"],
-
-["0x4c 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
-"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL",
-"P2SH,STRICTENC",
-"Basic PUSHDATA1 signedness check"],
-
-["all PUSHDATA forms are equivalent"],
-
-["0x4c 0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "PUSHDATA1 of 75 bytes equals direct push of it"],
-["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4c 0xFF 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "PUSHDATA2 of 255 bytes equals PUSHDATA1 of it"],
-
-["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"],
-
-["Numeric pushes"],
-
-["0x01 0x81", "0x4f EQUAL", "", "OP1_NEGATE pushes 0x81"],
-["0x01 0x01", "0x51 EQUAL", "", "OP_1  pushes 0x01"],
-["0x01 0x02", "0x52 EQUAL", "", "OP_2  pushes 0x02"],
-["0x01 0x03", "0x53 EQUAL", "", "OP_3  pushes 0x03"],
-["0x01 0x04", "0x54 EQUAL", "", "OP_4  pushes 0x04"],
-["0x01 0x05", "0x55 EQUAL", "", "OP_5  pushes 0x05"],
-["0x01 0x06", "0x56 EQUAL", "", "OP_6  pushes 0x06"],
-["0x01 0x07", "0x57 EQUAL", "", "OP_7  pushes 0x07"],
-["0x01 0x08", "0x58 EQUAL", "", "OP_8  pushes 0x08"],
-["0x01 0x09", "0x59 EQUAL", "", "OP_9  pushes 0x09"],
-["0x01 0x0a", "0x5a EQUAL", "", "OP_10 pushes 0x0a"],
-["0x01 0x0b", "0x5b EQUAL", "", "OP_11 pushes 0x0b"],
-["0x01 0x0c", "0x5c EQUAL", "", "OP_12 pushes 0x0c"],
-["0x01 0x0d", "0x5d EQUAL", "", "OP_13 pushes 0x0d"],
-["0x01 0x0e", "0x5e EQUAL", "", "OP_14 pushes 0x0e"],
-["0x01 0x0f", "0x5f EQUAL", "", "OP_15 pushes 0x0f"],
-["0x01 0x10", "0x60 EQUAL", "", "OP_16 pushes 0x10"],
-
-["Equivalency of different numeric encodings"],
-
-["0x02 0x8000", "128 NUMEQUAL", "", "0x8000 equals 128"],
-["0x01 0x00", "0 NUMEQUAL", "", "0x00 numequals 0"],
-["0x01 0x80", "0 NUMEQUAL", "", "0x80 (negative zero) numequals 0"],
-["0x02 0x0080", "0 NUMEQUAL", "", "0x0080 numequals 0"],
-["0x02 0x0500", "5 NUMEQUAL", "", "0x0500 numequals 5"],
-["0x03 0xff7f80", "0x02 0xffff NUMEQUAL", "", ""],
-["0x03 0xff7f00", "0x02 0xff7f NUMEQUAL", "", ""],
-["0x04 0xffff7f80", "0x03 0xffffff NUMEQUAL", "", ""],
-["0x04 0xffff7f00", "0x03 0xffff7f NUMEQUAL", "", ""],
-
-["Unevaluated non-minimal pushes are ignored"],
-
-["0 IF 0x4c 0x00 ENDIF 1", "", "MINIMALDATA", "non-minimal PUSHDATA1 ignored"],
-["0 IF 0x4d 0x0000 ENDIF 1", "", "MINIMALDATA", "non-minimal PUSHDATA2 ignored"],
-["0 IF 0x4c 0x00000000 ENDIF 1", "", "MINIMALDATA", "non-minimal PUSHDATA4 ignored"],
-["0 IF 0x01 0x81 ENDIF 1", "", "MINIMALDATA", "1NEGATE equiv"],
-["0 IF 0x01 0x01 ENDIF 1", "", "MINIMALDATA", "OP_1  equiv"],
-["0 IF 0x01 0x02 ENDIF 1", "", "MINIMALDATA", "OP_2  equiv"],
-["0 IF 0x01 0x03 ENDIF 1", "", "MINIMALDATA", "OP_3  equiv"],
-["0 IF 0x01 0x04 ENDIF 1", "", "MINIMALDATA", "OP_4  equiv"],
-["0 IF 0x01 0x05 ENDIF 1", "", "MINIMALDATA", "OP_5  equiv"],
-["0 IF 0x01 0x06 ENDIF 1", "", "MINIMALDATA", "OP_6  equiv"],
-["0 IF 0x01 0x07 ENDIF 1", "", "MINIMALDATA", "OP_7  equiv"],
-["0 IF 0x01 0x08 ENDIF 1", "", "MINIMALDATA", "OP_8  equiv"],
-["0 IF 0x01 0x09 ENDIF 1", "", "MINIMALDATA", "OP_9  equiv"],
-["0 IF 0x01 0x0a ENDIF 1", "", "MINIMALDATA", "OP_10 equiv"],
-["0 IF 0x01 0x0b ENDIF 1", "", "MINIMALDATA", "OP_11 equiv"],
-["0 IF 0x01 0x0c ENDIF 1", "", "MINIMALDATA", "OP_12 equiv"],
-["0 IF 0x01 0x0d ENDIF 1", "", "MINIMALDATA", "OP_13 equiv"],
-["0 IF 0x01 0x0e ENDIF 1", "", "MINIMALDATA", "OP_14 equiv"],
-["0 IF 0x01 0x0f ENDIF 1", "", "MINIMALDATA", "OP_15 equiv"],
-["0 IF 0x01 0x10 ENDIF 1", "", "MINIMALDATA", "OP_16 equiv"],
-
-["Numeric minimaldata rules are only applied when a stack item is numerically evaluated; the push itself is allowed"],
-
-["0x01 0x00", "1", "MINIMALDATA"],
-["0x01 0x80", "1", "MINIMALDATA"],
-["0x02 0x0180", "1", "MINIMALDATA"],
-["0x02 0x0100", "1", "MINIMALDATA"],
-["0x02 0x0200", "1", "MINIMALDATA"],
-["0x02 0x0300", "1", "MINIMALDATA"],
-["0x02 0x0400", "1", "MINIMALDATA"],
-["0x02 0x0500", "1", "MINIMALDATA"],
-["0x02 0x0600", "1", "MINIMALDATA"],
-["0x02 0x0700", "1", "MINIMALDATA"],
-["0x02 0x0800", "1", "MINIMALDATA"],
-["0x02 0x0900", "1", "MINIMALDATA"],
-["0x02 0x0a00", "1", "MINIMALDATA"],
-["0x02 0x0b00", "1", "MINIMALDATA"],
-["0x02 0x0c00", "1", "MINIMALDATA"],
-["0x02 0x0d00", "1", "MINIMALDATA"],
-["0x02 0x0e00", "1", "MINIMALDATA"],
-["0x02 0x0f00", "1", "MINIMALDATA"],
-["0x02 0x1000", "1", "MINIMALDATA"],
-
-["Valid version of the 'Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule' script_invalid test"],
-
-["1 0x02 0x0000", "PICK DROP", ""],
-["1 0x02 0x0000", "ROLL DROP 1", ""],
-["0x02 0x0000", "1ADD DROP 1", ""],
-["0x02 0x0000", "1SUB DROP 1", ""],
-["0x02 0x0000", "NEGATE DROP 1", ""],
-["0x02 0x0000", "ABS DROP 1", ""],
-["0x02 0x0000", "NOT DROP 1", ""],
-["0x02 0x0000", "0NOTEQUAL DROP 1", ""],
-
-["0 0x02 0x0000", "ADD DROP 1", ""],
-["0x02 0x0000 0", "ADD DROP 1", ""],
-["0 0x02 0x0000", "SUB DROP 1", ""],
-["0x02 0x0000 0", "SUB DROP 1", ""],
-["0 0x02 0x0000", "BOOLAND DROP 1", ""],
-["0x02 0x0000 0", "BOOLAND DROP 1", ""],
-["0 0x02 0x0000", "BOOLOR DROP 1", ""],
-["0x02 0x0000 0", "BOOLOR DROP 1", ""],
-["0 0x02 0x0000", "NUMEQUAL DROP 1", ""],
-["0x02 0x0000 1", "NUMEQUAL DROP 1", ""],
-["0 0x02 0x0000", "NUMEQUALVERIFY 1", ""],
-["0x02 0x0000 0", "NUMEQUALVERIFY 1", ""],
-["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", ""],
-["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", ""],
-["0 0x02 0x0000", "LESSTHAN DROP 1", ""],
-["0x02 0x0000 0", "LESSTHAN DROP 1", ""],
-["0 0x02 0x0000", "GREATERTHAN DROP 1", ""],
-["0x02 0x0000 0", "GREATERTHAN DROP 1", ""],
-["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", ""],
-["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", ""],
-["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", ""],
-["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", ""],
-["0 0x02 0x0000", "MIN DROP 1", ""],
-["0x02 0x0000 0", "MIN DROP 1", ""],
-["0 0x02 0x0000", "MAX DROP 1", ""],
-["0x02 0x0000 0", "MAX DROP 1", ""],
-
-["0x02 0x0000 0 0", "WITHIN DROP 1", ""],
-["0 0x02 0x0000 0", "WITHIN DROP 1", ""],
-["0 0 0x02 0x0000", "WITHIN DROP 1", ""],
-
-["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", ""],
-["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", ""],
-["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", ""],
-["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", ""],
-["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", ""],
-
-
-[
-    "0x47 0x3044022007415aa37ce7eaa6146001ac8bdefca0ddcba0e37c5dc08c4ac99392124ebac802207d382307fd53f65778b07b9c63b6e196edeadf0be719130c5db21ff1e700d67501",
-    "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
-    "",
-    "P2PK"
-],
-[
-    "0x47 0x3044022069d40999786aeb2fd874f9eb2636461a062dc963471627ed8390a3a5f9556f640220350132a52415ce622f2aadd07f791c591500917ec1f8c5edbc5381ef7942534d01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508",
-    "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG",
-    "",
-    "P2PKH"
-],
-[
-    "0x47 0x30440220519f2a6632ffa134c7811ea2819e9dcc951f0c7baf461f2dffdd09133f3b080a02203ec6bab5eb6619ed7f41b8701d7c6d70cfc83bb26c5c97f54b2ca6e304fc2bb581",
-    "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
-    "",
-    "P2PK anyonecanpay"
-],
-[
-    "0x47 0x30440220279dad2170ffb5639f0a1ea71fc462ee37d75d420d86f84c978bac523c09b7f20220683b2789f5c5528a9e0a0d78f6e40db3f616cf1adb5a5fdef117d5974795cfe201 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
-    "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
-    "P2SH",
-    "P2SH(P2PK)"
-],
-[
-    "0x47 0x3044022066acbfb5ac96b7cbf3f05a2aaf358c32438c45d1d7359dee9fc1ee636940735f02205606a03fd8cbf6a6fcbcba60c8abb1e385c0b5753cb57a97538159106fd3684e01 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
-    "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
-    "",
-    "P2SH(P2PKH), bad sig but no VERIFY_P2SH"
-],
-[
-    "0 0x47 0x3044022004e791dd30a64c70e55e84e150c002af9feb3ce0ab1f20e86c53d1209003927502205a60453987fcd72aebaaacebc8ce4b15449cdd79e54cc82cefb83e69dbcfeabf01 0x47 0x304402201d021808ce93dd8574cc4f99ae4f11b44305528b0aecbd9f156f08315173643802200944a0ea5c884bd86180aef76d8b1e444860776b251e47d2d6c651a1c6f9930801 0x47 0x30440220446336d7b7de05ebb5683b82b05248ec7d78e88ae8d6125985f5776c887a4cf90220674ab2b2c2f954ba1cf35457d273c90d0c0c1c224d0ae128628740e81129486801",
-    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
-    "",
-    "3-of-3"
-],
-[
-    "0 0x47 0x30440220288b06d057cf0eac434ed0c3be9257cc0ca144dd99c11cc8f1a49467a37d8e8002203c496c72253c528e6bc81c42e683aba974d46041a96ef7b00915c863eb2a702901 0x47 0x304402207ffb4da33f40cac839a43000a187bd76a1ee5bf95e46dc1534b38bb7bd0321db022038c078f29d1831f8eb68ffdc2634c654fb01c3467b6457b98ad220653bb2478501 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
-    "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
-    "P2SH",
-    "P2SH(2-of-3)"
-],
-[
-    "0x47 0x30440220001fff8863c84c0efc8eea5bffb7f388313f966f23a00ad3c0acc30ff5339684022016e6d78f51a3a1c362745931ca40b24f71cba2903dbfe5a6d392a9189127d83701",
-    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
-    "",
-    "P2PK with too much R padding but no DERSIG"
-],
-[
-    "0x48 0x304502202323d56f293842b544cacedd06baafb999196dfa1c2975314848c158ac606655022100514bd98186b8a3a1cc87f4aff76aed797781389f13f50d87bf95b2df6e488fcc01",
-    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
-    "",
-    "P2PK with too much S padding but no DERSIG"
-],
-[
-    "0x47 0x30440220d31c24bb6c08a496e7698a08fd41975115d7b55bfaa31cb2d573e09481e59a6702206a691239996434076b78a4e1cf46fc8e993b468a9c77fb1832186aa8040a61a201",
-    "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
-    "",
-    "P2PK with too little R padding but no DERSIG"
-],
-[
-    "0x47 0x30440220007c2cc7aef1801c2937447703c87ef2a3744209ad98da2abadd4ba8bb2e3ea00220503a275582c9f9e9ff30260c81b7f64b8b696f22105605cc8241fb76a797316201",
-    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
-    "",
-    "P2PK NOT with bad sig with too much R padding but no DERSIG"
-],
-[
-    "0x48 0x3045022021bf9184d94f208ac9f4757ebca9b1cbebf008cfc244fe5be1360b1b9aba0e92022100e55074f72f3a1bfddf2ea4ea7ba984f78822e136fe04c8f9c1363238e0233bd801",
-    "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
-    "STRICTENC",
-    "P2PK with high S but no LOW_S"
-],
-[
-    "0x47 0x3044022078d6c447887e88dcbe1bc5b613645280df6f4e5935648bc226e9d91da71b3216022047d6b7ef0949b228fc1b359afb8d50500268711354298217b983c26970790c7601",
-    "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
-    "",
-    "P2PK NOT with invalid hybrid pubkey but no STRICTENC"
-],
-[
-    "0 0x47 0x304402203b269b9fbc0936877bf855b5fb41757218d9548b246370d991442a5f5bd1c3440220235268a4eaa8c67e543c6e37da81dd36d3b1be2de6b4fef04113389ca6ddc04501",
-    "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
-    "",
-    "1-of-2 with the second 1 hybrid pubkey and no STRICTENC"
-],
-[
-    "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
-    "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
-    "STRICTENC",
-    "1-of-2 with the second 1 hybrid pubkey"
-],
-
-["
-CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and
-pubkeys in a specific order, and will exit early if the number of signatures
-left to check is greater than the number of keys left. As STRICTENC fails the
-script when it reaches an invalidly encoded signature or pubkey, we can use it
-to test the exact order in which signatures and pubkeys are evaluated by
-distinguishing CHECKMULTISIG returning false on the stack and the script as a
-whole failing.
-
-See also the corresponding inverted versions of these tests in script_invalid.json
-"],
-[
-    "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
-    "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
-    "STRICTENC",
-    "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey."
-],
-[
-    "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
-    "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
-    "STRICTENC",
-    "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature."
-],
-
-[
-    "0x47 0x304402204649e9517ef0377a8f8270bd423053fd98ddff62d74ea553e9579558abbb75e4022044a2b2344469c12e35ed898987711272b634733dd0f5e051288eceb04bd4669e05",
-    "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
-    "",
-    "P2PK with undefined hashtype but no STRICTENC"
-],
-[
-    "0x47 0x304402207f1cf1866a2df0bb4b8d84d0ade72aa3abb6aaab0639d608b23d9e10ead0c48202203caa97f22c3439443eea4b89f7f6729854df0f567a8184d6ecc6e8b6c68c3e9d05",
-    "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
-    "",
-    "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC"
-],
-[
-    "1 0x47 0x3044022046ce33d1771b0127dd4c4cef8fdc3218ebdfa60e3793ed700292d8ebd93fb1f402201029d47a414db83e96e31443c2d8b552f971469c4800f5eff7df2f0648521aed01 0x47 0x304402205c53911ad55b054920043962bbda98cf6e57e2db1cd5611138251490baabaa8702201dc80dfceae6007e7772dc13ff6e7ca66a983cb017fe5d46d30118462d83bcf801 0x47 0x304402201937e44a4ec12364f9d32f9d25e7ecbc68aee9ef90069af80efef4c05f6ace9602206c515101c00c75710b32ff7ff8dbaf7c9a0be6e86ed14a0755b47626604f31fd01",
-    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
-    "",
-    "3-of-3 with nonzero dummy but no NULLDUMMY"
-],
-[
-    "1 0x47 0x30440220195038dbc6b2ae1199f86a6777824f7c5149789d85f655a3534a4422b8fba38c02204df9db87d2eb9fe06edc66870d9ac4c9ce673459f9d43cee0347ce4ffb02ee5a01 0x47 0x3044022010a45f30c6fa97a186eba9e6b595ab87d3dfcbf05dcaf1f1b8e3e7bf39515bb802203474e78d3d372e5f5c0f8c257ce8300c4bb8f37c51d4a894e11a91b5817da6ed01 0x47 0x30440220039cffd8e39850f95112662b1220b14b3c0d3d8a2772e13c947bfbf96345a64e02204154bfa77e2c0134d5434353bed82141e5da1cc479954aa288d5f0671480a04b01",
-    "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
-    "",
-    "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY"
-],
-[
-    "0 0x47 0x3044022002a27769ee33db258bdf7a3792e7da4143ec4001b551f73e6a190b8d1bde449d02206742c56ccd94a7a2e16ca52fc1ae4a0aa122b0014a867a80de104f9cb18e472c01 DUP",
-    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
-    "",
-    "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY"
-],
-[
-    "0 0x47 0x304402203acf75dd59bbef171aeeedae4f1020b824195820db82575c2b323b8899f95de9022067df297d3a5fad049ba0bb81255d0e495643cbcf9abae9e396988618bc0c6dfe01 0x47 0x304402205f8b859230c1cab7d4e8de38ff244d2ebe046b64e8d3f4219b01e483c203490a022071bdc488e31b557f7d9e5c8a8bec90dc92289ca70fa317685f4f140e38b30c4601",
-    "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
-    "SIGPUSHONLY",
-    "2-of-2 with two identical keys and sigs pushed"
-],
-
-["The End"]
-]
diff --git a/tests/data/tx_valid.json b/tests/data/tx_valid.json
deleted file mode 100644
--- a/tests/data/tx_valid.json
+++ /dev/null
@@ -1,321 +0,0 @@
-[
-["The following are deserialized transactions which are valid."],
-["They are in the form"],
-["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"],
-["serializedTransaction, verifyFlags]"],
-["Objects that are only a single string (like this one) are ignored"],
-
-["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
-["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"],
-["See http://r6.ca/blog/20111119T211504Z.html"],
-["It is also the first OP_CHECKMULTISIG transaction in standard form"],
-[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
-"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
-
-["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
-["It is an OP_CHECKMULTISIG with an arbitrary extra byte stuffed into the signature at pos length - 2"],
-["The dummy byte is fine however, so the NULLDUMMY flag should be happy"],
-[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
-"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"],
-
-["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
-["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"],
-[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
-"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a01ff47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
-
-["As above, but using a OP_1"],
-[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
-"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
-
-["As above, but using a OP_1NEGATE"],
-[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
-"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
-
-["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"],
-["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"],
-[[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]],
-"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", "P2SH"],
-
-["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]],
-"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"],
-
-["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
-"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"],
-
-["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"],
-["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"],
-[[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"],
-["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]],
-"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", "P2SH"],
-
-["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"],
-["It results in signing the constant 1, instead of something generated based on the transaction,"],
-["when the input doing the signing has an index greater than the maximum output index"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"]],
-"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", "P2SH"],
-
-["An invalid P2SH Transaction"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
-"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "NONE"],
-
-["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]],
-"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", "P2SH"],
-
-["Tests for CheckTransaction()"],
-["MAX_MONEY output"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]],
-"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", "P2SH"],
-
-["MAX_MONEY output + 0 output"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]],
-"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", "P2SH"],
-
-["Coinbase of size 2"],
-["Note the input is just required to make the tester happy"],
-[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
-"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", "P2SH"],
-
-["Coinbase of size 100"],
-["Note the input is just required to make the tester happy"],
-[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
-"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", "P2SH"],
-
-["Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
-  ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
- "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"],
-
-["Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
-  ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
- "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"],
-
-["afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae which has several SIGHASH_SINGLE signatures"],
-[[["63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70", 0, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"],
- ["04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"],
- ["ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"]],
- "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", "P2SH"],
-
- ["ddc454a1c0c35c188c98976b17670f69e586d9c0f3593ea879928332f0a069e7, which spends an input that pushes using a PUSHDATA1 that is negative when read as signed"],
- [[["c5510a5dd97a25f43175af1fe649b707b1df8e1a41489bac33a23087027a2f48", 0, "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG"]],
- "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", "P2SH"],
-
-["Correct signature order"],
-["Note the input is just required to make the tester happy"],
-[[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]],
-"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"],
-
-["cc60b1f899ec0a69b7c3f25ddf32c4524096a9c5b01cbd84c6d0312a0c478984, which is a fairly strange transaction which relies on OP_CHECKSIG returning 0 when checking a completely invalid sig of length 0"],
-[[["cbebc4da731e8995fe97f6fadcd731b36ad40e5ecb31e38e904f6e5982fa09f7", 0, "0x2102085c6600657566acc2d6382a47bc3f324008d2aa10940dd7705a48aa2a5a5e33ac7c2103f5d0fb955f95dd6be6115ce85661db412ec6a08abcbfce7da0ba8297c6cc0ec4ac7c5379a820d68df9e32a147cffa36193c6f7c43a1c8c69cda530e1c6db354bfabdcfefaf3c875379a820f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226879a5479827701200122a59a5379827701200122a59a6353798277537982778779679a68"]],
-"0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", "P2SH"],
-
-["Empty pubkey"],
-[[["229257c295e7f555421c1bfec8538dd30a4b5c37c1c8810bbe83cafa7811652c", 0, "0x00 CHECKSIG NOT"]],
-"01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", "P2SH"],
-
-["Empty signature"],
-[[["9ca93cfd8e3806b9d9e2ba1cf64e3cc6946ee0119670b1796a09928d14ea25f7", 0, "0x21 0x028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02 CHECKSIG NOT"]],
-"0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", "P2SH"],
-
-[[["444e00ed7840d41f20ecd9c11d3f91982326c731a02f3c05748414a4fa9e59be", 0, "1 0x00 0x21 0x02136b04758b0b6e363e7a6fbe83aaf527a153db2b060d36cc29f7f8309ba6e458 2 CHECKMULTISIG"]],
-"0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", "P2SH"],
-
-[[["e16abbe80bf30c080f63830c8dbf669deaef08957446e95940227d8c5e6db612", 0, "1 0x21 0x03905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9f 0x00 2 CHECKMULTISIG"]],
-"010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", "P2SH"],
-
-[[["ebbcf4bfce13292bd791d6a65a2a858d59adbf737e387e40370d4e64cc70efb0", 0, "2 0x21 0x033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194 0x21 0x03a88b326f8767f4f192ce252afe33c94d25ab1d24f27f159b3cb3aa691ffe1423 2 CHECKMULTISIG NOT"]],
-"0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", "P2SH"],
-
-[[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]],
-"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", "P2SH"],
-
-
-["OP_CODESEPARATOR tests"],
-
-["Test that SignatureHash() removes OP_CODESEPARATOR with FindAndDelete()"],
-[[["bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224", 0, "CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]],
-"01000000012432b60dc72cebc1a27ce0969c0989c895bdd9e62e8234839117f8fc32d17fbc000000004a493046022100a576b52051962c25e642c0fd3d77ee6c92487048e5d90818bcf5b51abaccd7900221008204f8fb121be4ec3b24483b1f92d89b1b0548513a134e345c5442e86e8617a501ffffffff010000000000000000016a00000000", "P2SH"],
-[[["83e194f90b6ef21fa2e3a365b63794fb5daa844bdc9b25de30899fcfe7b01047", 0, "CODESEPARATOR CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]],
-"01000000014710b0e7cf9f8930de259bdc4b84aa5dfb9437b665a3e3a21ff26e0bf994e183000000004a493046022100a166121a61b4eeb19d8f922b978ff6ab58ead8a5a5552bf9be73dc9c156873ea02210092ad9bc43ee647da4f6652c320800debcf08ec20a094a0aaf085f63ecb37a17201ffffffff010000000000000000016a00000000", "P2SH"],
-
-["Hashed data starts at the CODESEPARATOR"],
-[[["326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CODESEPARATOR CHECKSIG"]],
-"01000000015ebaa001d8e4ec7a88703a3bcf69d98c874bca6299cca0f191512bf2a7826832000000004948304502203bf754d1c6732fbf87c5dcd81258aefd30f2060d7bd8ac4a5696f7927091dad1022100f5bcb726c4cf5ed0ed34cc13dadeedf628ae1045b7cb34421bc60b89f4cecae701ffffffff010000000000000000016a00000000", "P2SH"],
-
-["But only if execution has reached it"],
-[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]],
-"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH"],
-
-["CODESEPARATOR in an unexecuted IF block does not change what is hashed"],
-[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
-"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0100ffffffff010000000000000000016a00000000", "P2SH"],
-
-["As above, with the IF block executed"],
-[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
-"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH"],
-
-
-["CHECKSIG is legal in scriptSigs"],
-[[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
-"0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
-
-["Same semantics for OP_CODESEPARATOR"],
-[[["10c9f0effe83e97f80f067de2b11c6a00c3088a4bce42c5ae761519af9306f3c", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
-"01000000013c6f30f99a5161e75a2ce4bca488300ca0c6112bde67f0807fe983feeff0c91001000000e608646561646265656675ab61493046022100ce18d384221a731c993939015e3d1bcebafb16e8c0b5b5d14097ec8177ae6f28022100bcab227af90bab33c3fe0a9abfee03ba976ee25dc6ce542526e9b2e56e14b7f10121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac493046022100c3b93edcc0fd6250eb32f2dd8a0bba1754b0f6c3be8ed4100ed582f3db73eba2022100bf75b5bd2eff4d6bf2bda2e34a40fcc07d4aa3cf862ceaa77b47b81eff829f9a01ab21038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
-
-["Signatures are removed from the script they are in by FindAndDelete() in the CHECKSIG code; even multiple instances of one signature can be removed."],
-[[["6056ebd549003b10cbbd915cea0d82209fe40b8617104be917a26fa92cbe3d6f", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
-"01000000016f3dbe2ca96fa217e94b1017860be49f20820dea5c91bdcb103b0049d5eb566000000000fd1d0147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac47304402203757e937ba807e4a5da8534c17f9d121176056406a6465054bdd260457515c1a02200f02eccf1bec0f3a0d65df37889143c2e88ab7acec61a7b6f5aa264139141a2b0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
-
-["That also includes ahead of the opcode being executed."],
-[[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
-"01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
-
-["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."],
-
-["Here's an example on mainnet within a P2SH redeemScript. Remarkably it's a standard transaction in <0.9"],
-[[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"],
-  ["ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742", 0, "HASH160 0x14 0xd8dacdadb7462ae15cd906f1878706d0da8660e6 EQUAL"]],
-"0100000002f9cbafc519425637ba4227f8d0a0b7160b4e65168193d5af39747891de98b5b5000000006b4830450221008dd619c563e527c47d9bd53534a770b102e40faa87f61433580e04e271ef2f960220029886434e18122b53d5decd25f1f4acb2480659fea20aabd856987ba3c3907e0121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffff42e7988254800876b69f24676b3e0205b77be476512ca4d970707dd5c60598ab00000000fd260100483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53034930460221008431bdfa72bc67f9d41fe72e94c88fb8f359ffa30b33c72c121c5a877d922e1002210089ef5fc22dd8bfc6bf9ffdb01a9862d27687d424d1fefbab9e9c7176844a187a014c9052483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7153aeffffffff01a08601000000000017a914d8dacdadb7462ae15cd906f1878706d0da8660e68700000000", "P2SH"],
-
-["Same idea, but with bare CHECKMULTISIG"],
-[[["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"],
-  ["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]],
-"0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"],
-
-
-["CHECKLOCKTIMEVERIFY tests"],
-
-["By-height locks, with argument == 0 and == tx nLockTime"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
-"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 CHECKLOCKTIMEVERIFY 1"]],
-"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
-"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
-
-["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]],
-"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKLOCKTIMEVERIFY 1"]],
-"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]],
-"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
-
-["Any non-maxint nSequence is fine"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
-"010000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
-
-["The argument can be calculated rather than created directly by a PUSHDATA"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 1ADD CHECKLOCKTIMEVERIFY 1"]],
-"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
-
-["Perhaps even by an ADD producing a 5-byte result that is out of bounds for other opcodes"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 2147483647 ADD CHECKLOCKTIMEVERIFY 1"]],
-"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
-
-["5 byte non-minimally-encoded arguments are valid"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKLOCKTIMEVERIFY 1"]],
-"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
-
-["Valid CHECKLOCKTIMEVERIFY in scriptSig"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
-"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"],
-
-["Valid CHECKLOCKTIMEVERIFY in redeemScript"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]],
-"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"],
-
-["A transaction with a non-standard DER signature."],
-[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
-"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"],
-
-["CHECKSEQUENCEVERIFY tests"],
-
-["By-height locks, with argument == 0 and == txin.nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["By-time locks, with argument == 0 and == txin.nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["Upper sequence with upper sequence is fine"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["Argument 2^31 with various nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["Argument 2^32-1 with various nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["Argument 3<<31 with various nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["5 byte non-minimally-encoded operandss are valid"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["The argument can be calculated rather than created directly by a PUSHDATA"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["An ADD producing a 5-byte result that sets CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD NOP3 1"]],
-"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["Valid CHECKSEQUENCEVERIFY in scriptSig"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
-"02000000010001000000000000000000000000000000000000000000000000000000000000000000000251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["Valid CHECKSEQUENCEVERIFY in redeemScript"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]],
-"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-
-["Make diffs cleaner by leaving a comment here without comma at the end"]
-]
