packages feed

haskoin-core 0.19.0 → 0.20.0

raw patch · 33 files changed

+1715/−757 lines, 33 filesdep +base16dep +binarydep +bytesdep −base16-bytestringdep ~cerealPVP ok

version bump matches the API change (PVP)

Dependencies added: base16, binary, bytes

Dependencies removed: base16-bytestring

Dependency ranges changed: cereal

API changes (from Hackage documentation)

+ Haskoin.Address: instance Data.Binary.Class.Binary Haskoin.Address.Address
+ Haskoin.Address: instance Data.Bytes.Serial.Serial Haskoin.Address.Address
+ Haskoin.Block.Common: instance Data.Binary.Class.Binary Haskoin.Block.Common.Block
+ Haskoin.Block.Common: instance Data.Binary.Class.Binary Haskoin.Block.Common.BlockHash
+ Haskoin.Block.Common: instance Data.Binary.Class.Binary Haskoin.Block.Common.BlockHeader
+ Haskoin.Block.Common: instance Data.Binary.Class.Binary Haskoin.Block.Common.GetHeaders
+ Haskoin.Block.Common: instance Data.Binary.Class.Binary Haskoin.Block.Common.Headers
+ Haskoin.Block.Common: instance Data.Bytes.Serial.Serial Haskoin.Block.Common.Block
+ Haskoin.Block.Common: instance Data.Bytes.Serial.Serial Haskoin.Block.Common.BlockHash
+ Haskoin.Block.Common: instance Data.Bytes.Serial.Serial Haskoin.Block.Common.BlockHeader
+ Haskoin.Block.Common: instance Data.Bytes.Serial.Serial Haskoin.Block.Common.GetBlocks
+ Haskoin.Block.Common: instance Data.Bytes.Serial.Serial Haskoin.Block.Common.GetHeaders
+ Haskoin.Block.Common: instance Data.Bytes.Serial.Serial Haskoin.Block.Common.Headers
+ Haskoin.Block.Headers: instance Data.Binary.Class.Binary Haskoin.Block.Headers.BlockNode
+ Haskoin.Block.Headers: instance Data.Bytes.Serial.Serial Haskoin.Block.Headers.BlockNode
+ Haskoin.Block.Merkle: instance Data.Binary.Class.Binary Haskoin.Block.Merkle.MerkleBlock
+ Haskoin.Block.Merkle: instance Data.Bytes.Serial.Serial Haskoin.Block.Merkle.MerkleBlock
+ Haskoin.Constants: instance Data.Binary.Class.Binary Haskoin.Constants.Network
+ Haskoin.Constants: instance Data.Bytes.Serial.Serial Haskoin.Constants.Network
+ Haskoin.Crypto.Hash: instance Data.Binary.Class.Binary Haskoin.Crypto.Hash.CheckSum32
+ Haskoin.Crypto.Hash: instance Data.Binary.Class.Binary Haskoin.Crypto.Hash.Hash160
+ Haskoin.Crypto.Hash: instance Data.Binary.Class.Binary Haskoin.Crypto.Hash.Hash256
+ Haskoin.Crypto.Hash: instance Data.Binary.Class.Binary Haskoin.Crypto.Hash.Hash512
+ Haskoin.Crypto.Hash: instance Data.Bytes.Serial.Serial Haskoin.Crypto.Hash.CheckSum32
+ Haskoin.Crypto.Hash: instance Data.Bytes.Serial.Serial Haskoin.Crypto.Hash.Hash160
+ Haskoin.Crypto.Hash: instance Data.Bytes.Serial.Serial Haskoin.Crypto.Hash.Hash256
+ Haskoin.Crypto.Hash: instance Data.Bytes.Serial.Serial Haskoin.Crypto.Hash.Hash512
+ Haskoin.Keys.Common: instance Data.Binary.Class.Binary Haskoin.Keys.Common.PubKeyI
+ Haskoin.Keys.Common: instance Data.Bytes.Serial.Serial Haskoin.Keys.Common.PubKeyI
+ Haskoin.Keys.Extended: instance Data.Binary.Class.Binary Haskoin.Keys.Extended.DerivPath
+ Haskoin.Keys.Extended: instance Data.Binary.Class.Binary Haskoin.Keys.Extended.HardPath
+ Haskoin.Keys.Extended: instance Data.Binary.Class.Binary Haskoin.Keys.Extended.SoftPath
+ Haskoin.Keys.Extended: instance Data.Binary.Class.Binary Haskoin.Keys.Extended.XPrvKey
+ Haskoin.Keys.Extended: instance Data.Binary.Class.Binary Haskoin.Keys.Extended.XPubKey
+ Haskoin.Keys.Extended: instance Data.Bytes.Serial.Serial Haskoin.Keys.Extended.DerivPath
+ Haskoin.Keys.Extended: instance Data.Bytes.Serial.Serial Haskoin.Keys.Extended.HardPath
+ Haskoin.Keys.Extended: instance Data.Bytes.Serial.Serial Haskoin.Keys.Extended.SoftPath
+ Haskoin.Keys.Extended: instance Data.Bytes.Serial.Serial Haskoin.Keys.Extended.XPrvKey
+ Haskoin.Keys.Extended: instance Data.Bytes.Serial.Serial Haskoin.Keys.Extended.XPubKey
+ Haskoin.Network.Bloom: instance Data.Binary.Class.Binary Haskoin.Network.Bloom.BloomFilter
+ Haskoin.Network.Bloom: instance Data.Binary.Class.Binary Haskoin.Network.Bloom.BloomFlags
+ Haskoin.Network.Bloom: instance Data.Binary.Class.Binary Haskoin.Network.Bloom.FilterAdd
+ Haskoin.Network.Bloom: instance Data.Binary.Class.Binary Haskoin.Network.Bloom.FilterLoad
+ Haskoin.Network.Bloom: instance Data.Bytes.Serial.Serial Haskoin.Network.Bloom.BloomFilter
+ Haskoin.Network.Bloom: instance Data.Bytes.Serial.Serial Haskoin.Network.Bloom.BloomFlags
+ Haskoin.Network.Bloom: instance Data.Bytes.Serial.Serial Haskoin.Network.Bloom.FilterAdd
+ Haskoin.Network.Bloom: instance Data.Bytes.Serial.Serial Haskoin.Network.Bloom.FilterLoad
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.Addr
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.Alert
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.GetData
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.HostAddress
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.Inv
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.InvType
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.InvVector
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.MessageCommand
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.NetworkAddress
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.NotFound
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.Ping
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.Pong
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.Reject
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.RejectCode
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.VarInt
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.VarString
+ Haskoin.Network.Common: instance Data.Binary.Class.Binary Haskoin.Network.Common.Version
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.Addr
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.Alert
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.GetData
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.HostAddress
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.Inv
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.InvType
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.InvVector
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.MessageCommand
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.NetworkAddress
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.NotFound
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.Ping
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.Pong
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.Reject
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.RejectCode
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.VarInt
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.VarString
+ Haskoin.Network.Common: instance Data.Bytes.Serial.Serial Haskoin.Network.Common.Version
+ Haskoin.Network.Message: instance Data.Binary.Class.Binary Haskoin.Network.Message.MessageHeader
+ Haskoin.Network.Message: instance Data.Bytes.Serial.Serial Haskoin.Network.Message.MessageHeader
+ Haskoin.Script.Common: instance Data.Binary.Class.Binary Haskoin.Script.Common.Script
+ Haskoin.Script.Common: instance Data.Binary.Class.Binary Haskoin.Script.Common.ScriptOp
+ Haskoin.Script.Common: instance Data.Bytes.Serial.Serial Haskoin.Script.Common.Script
+ Haskoin.Script.Common: instance Data.Bytes.Serial.Serial Haskoin.Script.Common.ScriptOp
+ Haskoin.Transaction.Common: instance Data.Binary.Class.Binary Haskoin.Transaction.Common.OutPoint
+ Haskoin.Transaction.Common: instance Data.Binary.Class.Binary Haskoin.Transaction.Common.Tx
+ Haskoin.Transaction.Common: instance Data.Binary.Class.Binary Haskoin.Transaction.Common.TxHash
+ Haskoin.Transaction.Common: instance Data.Binary.Class.Binary Haskoin.Transaction.Common.TxIn
+ Haskoin.Transaction.Common: instance Data.Binary.Class.Binary Haskoin.Transaction.Common.TxOut
+ Haskoin.Transaction.Common: instance Data.Bytes.Serial.Serial Haskoin.Transaction.Common.OutPoint
+ Haskoin.Transaction.Common: instance Data.Bytes.Serial.Serial Haskoin.Transaction.Common.Tx
+ Haskoin.Transaction.Common: instance Data.Bytes.Serial.Serial Haskoin.Transaction.Common.TxHash
+ Haskoin.Transaction.Common: instance Data.Bytes.Serial.Serial Haskoin.Transaction.Common.TxIn
+ Haskoin.Transaction.Common: instance Data.Bytes.Serial.Serial Haskoin.Transaction.Common.TxOut
+ Haskoin.Util: decodeHexLazy :: Text -> Maybe ByteString
+ Haskoin.Util: encodeHexLazy :: ByteString -> Text
+ Haskoin.Util: getInt32be :: MonadGet m => m Int32
+ Haskoin.Util: getInt64be :: MonadGet m => m Int64
+ Haskoin.Util: getIntMap :: MonadGet m => m Int -> m a -> m (IntMap a)
+ Haskoin.Util: getInteger :: MonadGet m => m Integer
+ Haskoin.Util: getLengthBytes :: MonadGet m => m ByteString
+ Haskoin.Util: getList :: MonadGet m => m a -> m [a]
+ Haskoin.Util: getMaybe :: MonadGet m => m a -> m (Maybe a)
+ Haskoin.Util: getTwo :: MonadGet m => m a -> m b -> m (a, b)
+ Haskoin.Util: putInt32be :: MonadPut m => Int32 -> m ()
+ Haskoin.Util: putInt64be :: MonadPut m => Int64 -> m ()
+ Haskoin.Util: putIntMap :: MonadPut m => (Int -> m ()) -> (a -> m ()) -> IntMap a -> m ()
+ Haskoin.Util: putInteger :: MonadPut m => Integer -> m ()
+ Haskoin.Util: putLengthBytes :: MonadPut m => ByteString -> m ()
+ Haskoin.Util: putList :: MonadPut m => (a -> m ()) -> [a] -> m ()
+ Haskoin.Util: putMaybe :: MonadPut m => (a -> m ()) -> Maybe a -> m ()
+ Haskoin.Util: putTwo :: MonadPut m => (a -> m ()) -> (b -> m ()) -> (a, b) -> m ()
- Haskoin.Crypto.Signature: getSig :: Get Sig
+ Haskoin.Crypto.Signature: getSig :: MonadGet m => m Sig
- Haskoin.Crypto.Signature: putSig :: Putter Sig
+ Haskoin.Crypto.Signature: putSig :: MonadPut m => Sig -> m ()
- Haskoin.Keys.Extended: getXPrvKey :: Network -> Get XPrvKey
+ Haskoin.Keys.Extended: getXPrvKey :: MonadGet m => Network -> m XPrvKey
- Haskoin.Keys.Extended: getXPubKey :: Network -> Get XPubKey
+ Haskoin.Keys.Extended: getXPubKey :: MonadGet m => Network -> m XPubKey
- Haskoin.Keys.Extended: putXPrvKey :: Network -> Putter XPrvKey
+ Haskoin.Keys.Extended: putXPrvKey :: MonadPut m => Network -> XPrvKey -> m ()
- Haskoin.Keys.Extended: putXPubKey :: Network -> Putter XPubKey
+ Haskoin.Keys.Extended: putXPubKey :: MonadPut m => Network -> XPubKey -> m ()
- Haskoin.Network.Common: putVarInt :: Integral a => a -> Put
+ Haskoin.Network.Common: putVarInt :: (MonadPut m, Integral a) => a -> m ()
- Haskoin.Network.Message: getMessage :: Network -> Get Message
+ Haskoin.Network.Message: getMessage :: MonadGet m => Network -> m Message
- Haskoin.Network.Message: putMessage :: Network -> Putter Message
+ Haskoin.Network.Message: putMessage :: MonadPut m => Network -> Message -> m ()
- Haskoin.Util.Arbitrary.Util: testSerial :: (Eq a, Show a, Typeable a, Serialize a) => Gen a -> Spec
+ Haskoin.Util.Arbitrary.Util: testSerial :: (Eq a, Show a, Typeable a, Serial a) => Gen a -> Spec

Files

CHANGELOG.md view
@@ -4,6 +4,11 @@ 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.20.0+### Chaged+- Use bytes instead of binary or cereal.+ ## 0.19.0 ### Added - Hashable instances for extended keys.
haskoin-core.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.34.2.+-- This file has been generated from package.yaml by hpack version 0.33.0. -- -- see: https://github.com/sol/hpack ----- hash: 90de304467308666144472c303ad361258687f7e36e27e916ba836799ea6833c+-- hash: f90b7b9353df059b5744c2454f8f514133d3e989a66c8137a87030db88a73a2a  name:           haskoin-core-version:        0.19.0+version:        0.20.0 synopsis:       Bitcoin & Bitcoin Cash library for Haskell description:    Please see the README on GitHub at <https://github.com/haskoin/haskoin-core#readme> category:       Bitcoin, Finance, Network@@ -94,9 +94,11 @@     , aeson >=1.4.6.0     , array >=0.5.4.0     , base >=4.9 && <5-    , base16-bytestring >=0.1.1.6+    , base16 >=0.3.0.1+    , binary >=0.8.8+    , bytes >=0.17     , bytestring >=0.10.10.0-    , cereal >=0.5.8.1+    , cereal >=0.5.8     , conduit >=1.3.1.2     , containers >=0.6.2.1     , cryptonite >=0.26@@ -147,9 +149,11 @@     , aeson >=1.4.6.0     , array >=0.5.4.0     , base >=4.9 && <5-    , base16-bytestring >=0.1.1.6+    , base16 >=0.3.0.1+    , binary >=0.8.8+    , bytes >=0.17     , bytestring >=0.10.10.0-    , cereal >=0.5.8.1+    , cereal >=0.5.8     , conduit >=1.3.1.2     , containers >=0.6.2.1     , cryptonite >=0.26
src/Haskoin/Address.hs view
@@ -58,12 +58,17 @@ import           Data.Aeson               as A import           Data.Aeson.Encoding      as A import           Data.Aeson.Types+import           Data.Binary              (Binary (..)) import           Data.ByteString          (ByteString) import qualified Data.ByteString          as B+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Hashable import           Data.Maybe-import           Data.Serialize           as S+import           Data.Serialize           (Serialize (..)) import           Data.Text                (Text)+import qualified Data.Text                as T import           Data.Word                (Word8) import           GHC.Generics             (Generic) import           Haskoin.Address.Base58@@ -102,8 +107,48 @@          { getAddrVersion :: !Word8          , getAddrData    :: !ByteString          }-    deriving (Eq, Ord, Generic, Show, Read, Serialize, Hashable, NFData)+    deriving+        (Eq, Ord, Generic, Show, Read, Hashable, NFData) +instance Serial Address where+    serialize (PubKeyAddress k) = do+        putWord8 0x00+        serialize k+    serialize (ScriptAddress s) = do+        putWord8 0x01+        serialize s+    serialize (WitnessPubKeyAddress h) = do+        putWord8 0x02+        serialize h+    serialize (WitnessScriptAddress s) = do+        putWord8 0x03+        serialize s+    serialize (WitnessAddress v d) = do+        putWord8 0x04+        putWord8 v+        putWord64be (fromIntegral (B.length d))+        putByteString d++    deserialize =+        getWord8 >>= \case+        0x00 -> PubKeyAddress <$> deserialize+        0x01 -> ScriptAddress <$> deserialize+        0x02 -> WitnessPubKeyAddress <$> deserialize+        0x03 -> WitnessScriptAddress <$> deserialize+        0x04 -> WitnessAddress <$> getWord8 <*>+                (getByteString . fromIntegral =<< getWord64be)+        b -> fail . T.unpack $+             "Could not decode address type byte: " <>+             encodeHex (B.singleton b)++instance Serialize Address where+    put = serialize+    get = deserialize++instance Binary Address where+    put = serialize+    get = deserialize+ -- | 'Address' pays to a public key hash. isPubKeyAddress :: Address -> Bool isPubKeyAddress PubKeyAddress {} = True@@ -148,19 +193,19 @@ addrToText :: Network -> Address -> Maybe Text addrToText net a@PubKeyAddress {getAddrHash160 = h}     | isNothing (getCashAddrPrefix net) =-        Just . encodeBase58Check . runPut $ base58put net a-    | otherwise = cashAddrEncode net 0 (S.encode h)+        Just . encodeBase58Check . runPutS $ base58put net a+    | otherwise = cashAddrEncode net 0 (runPutS $ serialize h) addrToText net a@ScriptAddress {getAddrHash160 = h}     | isNothing (getCashAddrPrefix net) =-        Just . encodeBase58Check . runPut $ base58put net a+        Just . encodeBase58Check . runPutS $ base58put net a     | otherwise =-        cashAddrEncode net 1 (S.encode h)+        cashAddrEncode net 1 (runPutS $ serialize h) addrToText net WitnessPubKeyAddress {getAddrHash160 = h} = do     hrp <- getBech32Prefix net-    segwitEncode hrp 0 (B.unpack (S.encode h))+    segwitEncode hrp 0 (B.unpack (runPutS $ serialize h)) addrToText net WitnessScriptAddress {getAddrHash256 = h} = do     hrp <- getBech32Prefix net-    segwitEncode hrp 0 (B.unpack (S.encode h))+    segwitEncode hrp 0 (B.unpack (runPutS $ serialize h)) addrToText net WitnessAddress {getAddrVersion = v, getAddrData = d} = do     hrp <- getBech32Prefix net     segwitEncode hrp v (B.unpack d)@@ -174,8 +219,8 @@ cashToAddr net txt = do     (ver, bs) <- cashAddrDecode net txt     case ver of-        0 -> PubKeyAddress <$> eitherToMaybe (S.decode bs)-        1 -> ScriptAddress <$> eitherToMaybe (S.decode bs)+        0 -> PubKeyAddress <$> eitherToMaybe (runGetS deserialize bs)+        1 -> ScriptAddress <$> eitherToMaybe (runGetS deserialize bs)         _ -> Nothing  bech32ToAddr :: Network -> Text -> Maybe Address@@ -184,19 +229,19 @@     (ver, bs) <- second B.pack <$> segwitDecode hrp txt     case ver of         0 -> case B.length bs of-            20 -> WitnessPubKeyAddress <$> eitherToMaybe (S.decode bs)-            32 -> WitnessScriptAddress <$> eitherToMaybe (S.decode bs)+            20 -> WitnessPubKeyAddress <$> eitherToMaybe (runGetS deserialize bs)+            32 -> WitnessScriptAddress <$> eitherToMaybe (runGetS deserialize bs)             _  -> Nothing         _ -> Just $ WitnessAddress ver bs  base58ToAddr :: Network -> Text -> Maybe Address base58ToAddr net txt =-    eitherToMaybe . runGet (base58get net) =<< decodeBase58Check txt+    eitherToMaybe . runGetS (base58get net) =<< decodeBase58Check txt -base58get :: Network -> Get Address+base58get :: MonadGet m => Network -> m Address base58get net = do     pfx <- getWord8-    addr <- S.get+    addr <- deserialize     f pfx addr   where     f x a@@ -204,18 +249,18 @@         | x == getScriptPrefix net = return $ ScriptAddress a         | otherwise = fail "Does not recognize address prefix" -base58put :: Network -> Putter Address+base58put :: MonadPut m => Network -> Address -> m () base58put net (PubKeyAddress h) = do         putWord8 (getAddrPrefix net)-        put h+        serialize h base58put net (ScriptAddress h) = do         putWord8 (getScriptPrefix net)-        put h+        serialize h base58put _ _ = error "Cannot serialize this address as Base58"  -- | Obtain a standard pay-to-public-key-hash address from a public key. pubKeyAddr :: PubKeyI -> Address-pubKeyAddr = PubKeyAddress . addressHash . S.encode+pubKeyAddr = PubKeyAddress . addressHash . runPutS . serialize  -- | Obtain a standard pay-to-public-key-hash (P2PKH) address from a 'Hash160'. p2pkhAddr :: Hash160 -> Address@@ -224,13 +269,18 @@ -- | Obtain a SegWit pay-to-witness-public-key-hash (P2WPKH) address from a -- public key. pubKeyWitnessAddr :: PubKeyI -> Address-pubKeyWitnessAddr = WitnessPubKeyAddress . addressHash . S.encode+pubKeyWitnessAddr = WitnessPubKeyAddress . addressHash . runPutS . serialize  -- | Obtain a backwards-compatible SegWit P2SH-P2WPKH address from a public key. pubKeyCompatWitnessAddr :: PubKeyI -> Address pubKeyCompatWitnessAddr =     p2shAddr .-    addressHash . encodeOutputBS . PayWitnessPKHash . addressHash . S.encode+    addressHash .+    encodeOutputBS .+    PayWitnessPKHash .+    addressHash .+    runPutS .+    serialize  -- | Obtain a SegWit pay-to-witness-public-key-hash (P2WPKH) address from a -- 'Hash160'.@@ -264,11 +314,11 @@ addressToOutput :: Address -> ScriptOutput addressToOutput =     \case-        PubKeyAddress h -> PayPKHash h-        ScriptAddress h -> PayScriptHash h+        PubKeyAddress h        -> PayPKHash h+        ScriptAddress h        -> PayScriptHash h         WitnessPubKeyAddress h -> PayWitnessPKHash h         WitnessScriptAddress h -> PayWitnessScriptHash h-        WitnessAddress v d -> PayWitness v d+        WitnessAddress v d     -> PayWitness v d  -- | Get output script AST for an 'Address'. addressToScript :: Address -> Script@@ -276,7 +326,7 @@  -- | Encode address as output script in 'ByteString' form. addressToScriptBS :: Address -> ByteString-addressToScriptBS = S.encode . addressToScript+addressToScriptBS = runPutS . serialize . addressToScript  -- | Decode an output script into an 'Address' if it has such representation. scriptToAddress :: Script -> Either String Address@@ -292,18 +342,18 @@ outputAddress :: ScriptOutput -> Maybe Address outputAddress =     \case-        PayPKHash h -> Just $ PubKeyAddress h-        PayScriptHash h -> Just $ ScriptAddress h-        PayPK k -> Just $ pubKeyAddr k-        PayWitnessPKHash h -> Just $ WitnessPubKeyAddress h+        PayPKHash h            -> Just $ PubKeyAddress h+        PayScriptHash h        -> Just $ ScriptAddress h+        PayPK k                -> Just $ pubKeyAddr k+        PayWitnessPKHash h     -> Just $ WitnessPubKeyAddress h         PayWitnessScriptHash h -> Just $ WitnessScriptAddress h-        PayWitness v d -> Just $ WitnessAddress v d-        _ -> Nothing+        PayWitness v d         -> Just $ WitnessAddress v d+        _                      -> Nothing  -- | Infer the 'Address' of a 'ScriptInput'. inputAddress :: ScriptInput -> Maybe Address inputAddress =     \case         (RegularInput (SpendPKHash _ key)) -> Just $ pubKeyAddr key-        (ScriptHashInput _ rdm) -> Just $ payToScriptAddress rdm-        _ -> Nothing+        (ScriptHashInput _ rdm)            -> Just $ payToScriptAddress rdm+        _                                  -> Nothing
src/Haskoin/Address/Base58.hs view
@@ -23,8 +23,10 @@ import           Data.ByteString         (ByteString) import qualified Data.ByteString         as BS import qualified Data.ByteString.Char8   as C+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial 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@@ -90,7 +92,7 @@ -- the checksum as 'Base58'. encodeBase58Check :: ByteString -> Base58 encodeBase58Check bs =-    encodeBase58 $ BS.append bs $ encode $ checkSum32 bs+    encodeBase58 $ BS.append bs $ runPutS $ serialize $ checkSum32 bs  -- | Decode a 'Base58'-encoded string that contains a checksum. This function -- returns 'Nothing' if the input string contains invalid 'Base58' characters or@@ -99,5 +101,5 @@ decodeBase58Check bs = do     rs <- decodeBase58 bs     let (res, chk) = BS.splitAt (BS.length rs - 4) rs-    guard $ chk == encode (checkSum32 res)+    guard $ chk == runPutS (serialize (checkSum32 res))     return res
src/Haskoin/Block/Common.hs view
@@ -36,15 +36,19 @@                                              Value (..), object, toJSON,                                              withObject, withText, (.:), (.=)) import           Data.Aeson.Encoding        (pairs, unsafeToEncoding)+import           Data.Binary                (Binary (..)) import           Data.Bits                  (shiftL, shiftR, (.&.), (.|.)) import qualified Data.ByteString            as B import           Data.ByteString.Builder    (char7)+import qualified Data.ByteString.Lazy       as BL+import           Data.Bytes.Get             (MonadGet, getWord32le, runGetL,+                                             runGetS)+import           Data.Bytes.Put             (MonadPut, putWord32le, runPutL,+                                             runPutS)+import           Data.Bytes.Serial          (Serial (..)) 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.Serialize             (Serialize (..)) import           Data.String                (IsString, fromString) import           Data.String.Conversions    (cs) import           Data.Text                  (Text)@@ -69,17 +73,25 @@     }     deriving (Eq, Show, Read, Generic, Hashable, NFData) -instance Serialize Block where-    get = do-        header <- get-        (VarInt c) <- get-        txs <- replicateM (fromIntegral c) get+instance Serial Block where+    deserialize = do+        header <- deserialize+        (VarInt c) <- deserialize+        txs <- replicateM (fromIntegral c) deserialize         return $ Block header txs-    put (Block h txs) = do-        put h+    serialize (Block h txs) = do+        serialize h         putVarInt $ length txs-        forM_ txs put+        forM_ txs serialize +instance Serialize Block where+    get = deserialize+    put = serialize++instance Binary Block where+    get = deserialize+    put = serialize+ instance ToJSON Block where     toJSON (Block h t) = object ["header" .= h, "transactions" .= t]     toEncoding (Block h t) = pairs $ "header" .= h <> "transactions" .= t@@ -92,8 +104,16 @@ -- | Block header hash. To be serialized reversed for display purposes. newtype BlockHash = BlockHash     { getBlockHash :: Hash256-    } deriving (Eq, Ord, Generic, Hashable, Serialize, NFData)+    } deriving (Eq, Ord, Generic, Hashable, Serial, NFData) +instance Serialize BlockHash where+    put = serialize+    get = deserialize++instance Binary BlockHash where+    put = serialize+    get = deserialize+ instance Show BlockHash where     showsPrec _ = shows . blockHashToHex @@ -115,19 +135,21 @@     toJSON = String . blockHashToHex     toEncoding h =         unsafeToEncoding $-        char7 '"' <> hexBuilder (B.reverse (encode h)) <> char7 '"'+        char7 '"' <>+        hexBuilder (BL.reverse (runPutL (serialize h))) <>+        char7 '"'  -- | 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 (B.reverse (encode h))+blockHashToHex (BlockHash h) = encodeHex (B.reverse (runPutS (serialize h)))  -- | Convert a human-readable hex block hash into a 'BlockHash'. Bytes are -- reversed as normal. hexToBlockHash :: Text -> Maybe BlockHash hexToBlockHash hex = do     bs <- B.reverse <$> decodeHex hex-    h <- eitherToMaybe (decode bs)+    h <- eitherToMaybe (runGetS deserialize bs)     return $ BlockHash h  -- | Data type recording information of a 'Block'. The hash of a block is@@ -157,7 +179,7 @@         object             [ "version" .= v             , "prevblock" .= p-            , "merkleroot" .= encodeHex (encode m)+            , "merkleroot" .= encodeHex (runPutS (serialize m))             , "timestamp" .= t             , "bits" .= b             , "nonce" .= n@@ -166,7 +188,7 @@         pairs             ( "version" .= v            <> "prevblock" .= p-           <> "merkleroot" .= encodeHex (encode m)+           <> "merkleroot" .= encodeHex (runPutS (serialize m))            <> "timestamp" .= t            <> "bits" .= b            <> "nonce" .= n@@ -182,13 +204,17 @@                         <*> o .: "bits"                         <*> o .: "nonce"       where-        f = maybe mzero return . (eitherToMaybe . decode =<<) . decodeHex+        f = maybe+            mzero+            return .+            (eitherToMaybe . runGetS deserialize =<<) .+            decodeHex -instance Serialize BlockHeader where-    get = do+instance Serial BlockHeader where+    deserialize = do         v <- getWord32le-        p <- get-        m <- get+        p <- deserialize+        m <- deserialize         t <- getWord32le         b <- getWord32le         n <- getWord32le@@ -201,17 +227,25 @@                 , blockBits = b                 , bhNonce = n                 }-    put (BlockHeader v p m bt bb n) = do+    serialize (BlockHeader v p m bt bb n) = do         putWord32le v-        put p-        put m+        serialize p+        serialize m         putWord32le bt         putWord32le bb         putWord32le n +instance Binary BlockHeader where+    put = serialize+    get = deserialize++instance Serialize BlockHeader where+    put = serialize+    get = deserialize+ -- | Compute hash of 'BlockHeader'. headerHash :: BlockHeader -> BlockHash-headerHash = BlockHash . doubleSHA256 . encode+headerHash = BlockHash . doubleSHA256 . runPutS . serialize  -- | 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.@@ -236,18 +270,26 @@     }     deriving (Eq, Show, Read, Generic, NFData) -instance Serialize GetBlocks where-    get = GetBlocks <$> getWord32le <*> (repList =<< get) <*> get+instance Serial GetBlocks where+    deserialize =+        GetBlocks+        <$> getWord32le+        <*> (repList =<< deserialize)+        <*> deserialize       where-        repList (VarInt c) = replicateM (fromIntegral c) get-    put (GetBlocks v xs h) = putGetBlockMsg v xs h+        repList (VarInt c) = replicateM (fromIntegral c) deserialize+    serialize (GetBlocks v xs h) = putGetBlockMsg v xs h -putGetBlockMsg :: Word32 -> BlockLocator -> BlockHash -> Put+instance Serialize GetBlocks where+    put = serialize+    get = deserialize++putGetBlockMsg :: MonadPut m => Word32 -> BlockLocator -> BlockHash -> m () putGetBlockMsg v xs h = do     putWord32le v     putVarInt $ length xs-    forM_ xs put-    put h+    forM_ xs serialize+    serialize h  -- | Similar to the 'GetBlocks' message type but for retrieving block headers -- only. The response to a 'GetHeaders' request is a 'Headers' message@@ -263,12 +305,24 @@     }     deriving (Eq, Show, Read, Generic, NFData) -instance Serialize GetHeaders where-    get = GetHeaders <$> getWord32le <*> (repList =<< get) <*> get+instance Serial GetHeaders where+    deserialize =+        GetHeaders+        <$> getWord32le+        <*> (repList =<< deserialize)+        <*> deserialize       where-        repList (VarInt c) = replicateM (fromIntegral c) get-    put (GetHeaders v xs h) = putGetBlockMsg v xs h+        repList (VarInt c) = replicateM (fromIntegral c) deserialize+    serialize (GetHeaders v xs h) = putGetBlockMsg v xs h +instance Serialize GetHeaders where+    put = serialize+    get = deserialize++instance Binary GetHeaders where+    put = serialize+    get = deserialize+ -- | 'BlockHeader' type with a transaction count as 'VarInt' type BlockHeaderCount = (BlockHeader, VarInt) @@ -279,14 +333,22 @@       headersList :: [BlockHeaderCount]     } deriving (Eq, Show, Read, Generic, NFData) -instance Serialize Headers where-    get = Headers <$> (repList =<< get)+instance Serial Headers where+    deserialize = Headers <$> (repList =<< deserialize)       where         repList (VarInt c) = replicateM (fromIntegral c) action-        action = liftM2 (,) get get-    put (Headers xs) = do+        action = liftM2 (,) deserialize deserialize+    serialize (Headers xs) = do         putVarInt $ length xs-        forM_ xs $ \(a, b) -> put a >> put b+        forM_ xs $ \(a, b) -> serialize a >> serialize b++instance Serialize Headers where+    put = serialize+    get = deserialize++instance Binary Headers where+    put = serialize+    get = deserialize  -- | Decode the compact number used in the difficulty target of a block. --
src/Haskoin/Block/Headers.hs view
@@ -75,20 +75,21 @@ import           Control.Monad.State.Strict  as State (StateT, get, gets, lift,                                                        modify) import           Control.Monad.Trans.Maybe+import           Data.Binary                 (Binary (..)) import           Data.Bits                   (shiftL, shiftR, (.&.)) import qualified Data.ByteString             as B import           Data.ByteString.Short       (ShortByteString, fromShort,                                               toShort)+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Function               (on)-import           Data.Hashable import           Data.HashMap.Strict         (HashMap) import qualified Data.HashMap.Strict         as HashMap+import           Data.Hashable 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.Serialize              (Serialize (..)) import           Data.Typeable               (Typeable) import           Data.Word                   (Word32, Word64) import           GHC.Generics                (Generic)@@ -123,26 +124,34 @@           }     deriving (Show, Read, Generic, Hashable, NFData) -instance Serialize BlockNode where-    get = do-        nodeHeader <- S.get+instance Serial BlockNode where+    deserialize = do+        nodeHeader <- deserialize         nodeHeight <- getWord32le-        nodeWork <- S.get+        nodeWork   <- getInteger         if nodeHeight == 0             then do                 let nodeSkip = headerHash nodeHeader                 return BlockNode {..}             else do-                nodeSkip <- S.get+                nodeSkip <- deserialize                 return BlockNode {..}-    put bn = do-        put $ nodeHeader bn+    serialize bn = do+        serialize $ nodeHeader bn         putWord32le $ nodeHeight bn-        put $ nodeWork bn+        putInteger $ nodeWork bn         case nodeHeight bn of             0 -> return ()-            _ -> put $ nodeSkip bn+            _ -> serialize $ nodeSkip bn +instance Serialize BlockNode where+    put = serialize+    get = deserialize++instance Binary BlockNode where+    put = serialize+    get = deserialize+ instance Eq BlockNode where     (==) = (==) `on` nodeHeader @@ -187,7 +196,7 @@ genesisMap net =     HashMap.singleton         (shortBlockHash (headerHash (getGenesisHeader net)))-        (toShort (encode (genesisNode net)))+        (toShort (runPutS (serialize (genesisNode net))))  -- | Add block header to memory block map. addBlockHeaderMemory :: BlockNode -> HeaderMemory -> HeaderMemory@@ -199,20 +208,21 @@ getBlockHeaderMemory :: BlockHash -> HeaderMemory -> Maybe BlockNode getBlockHeaderMemory bh HeaderMemory {..} = do     bs <- shortBlockHash bh `HashMap.lookup` memoryHeaderMap-    eitherToMaybe . decode $ fromShort bs+    eitherToMaybe . runGetS deserialize $ 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+shortBlockHash =+    either error id . runGetS deserialize . B.take 8 . runPutS . serialize  -- | Add a block to memory-based block map. addBlockToMap :: BlockNode -> BlockMap -> BlockMap addBlockToMap node =     HashMap.insert     (shortBlockHash $ headerHash $ nodeHeader node)-    (toShort $ encode node)+    (toShort $ runPutS $ serialize node)  -- | Get the ancestor of the provided 'BlockNode' at the specified -- 'BlockHeight'.@@ -635,7 +645,7 @@ middleBlock a b =     getAncestor h b >>= \case         Nothing -> error "You fell into a pit full of mud and snakes"-        Just x -> return x+        Just x  -> return x   where     h = middleOf (nodeHeight a) (nodeHeight b) @@ -797,7 +807,7 @@  -- | Returns the proof of work of a block header hash as an 'Integer' number. blockPOW :: BlockHash -> Integer-blockPOW =  bsToInteger . B.reverse . encode+blockPOW =  bsToInteger . B.reverse . runPutS . serialize  -- | 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@@ -867,7 +877,7 @@     bh' = mineBlock net seed bh         { prevBlock = headerHash bh           -- Just to make it different in every header-        , merkleRoot = sha256 $ encode seed+        , merkleRoot = sha256 $ runPutS $ serialize seed         }  -- | Find the last common block ancestor between provided block headers.
src/Haskoin/Block/Merkle.hs view
@@ -35,14 +35,16 @@  import           Control.DeepSeq import           Control.Monad              (forM_, replicateM, when)+import           Data.Binary                (Binary (..)) import           Data.Bits import qualified Data.ByteString            as BS+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Either                (isRight) import           Data.Hashable import           Data.Maybe-import           Data.Serialize             (Serialize, encode, get, put)-import           Data.Serialize.Get         (getWord32le, getWord8)-import           Data.Serialize.Put         (putWord32le, putWord8)+import           Data.Serialize             (Serialize (..)) import           Data.Word                  (Word32, Word8) import           GHC.Generics import           Haskoin.Block.Common@@ -74,26 +76,33 @@                 , mFlags          :: !FlagBits                 } deriving (Eq, Show, Read, Generic, Hashable, NFData) -instance Serialize MerkleBlock where--    get = do-        header <- get+instance Serial MerkleBlock where+    deserialize = do+        header <- deserialize         ntx    <- getWord32le-        (VarInt matchLen) <- get-        hashes <- replicateM (fromIntegral matchLen) get-        (VarInt flagLen)  <- get+        (VarInt matchLen) <- deserialize+        hashes <- replicateM (fromIntegral matchLen) deserialize+        (VarInt flagLen)  <- deserialize         ws <- replicateM (fromIntegral flagLen) getWord8         return $ MerkleBlock header ntx hashes (decodeMerkleFlags ws) -    put (MerkleBlock h ntx hashes flags) = do-        put h+    serialize (MerkleBlock h ntx hashes flags) = do+        serialize h         putWord32le ntx         putVarInt $ length hashes-        forM_ hashes put+        forM_ hashes serialize         let ws = encodeMerkleFlags flags         putVarInt $ length ws         forM_ ws putWord8 +instance Binary MerkleBlock where+    put = serialize+    get = deserialize++instance Serialize MerkleBlock where+    put = serialize+    get = deserialize+ -- | Unpack Merkle flags into 'FlagBits' structure. decodeMerkleFlags :: [Word8] -> FlagBits decodeMerkleFlags ws =@@ -126,7 +135,7 @@  -- | Concatenate and compute double SHA256. hash2 :: Hash256 -> Hash256 -> Hash256-hash2 a b = doubleSHA256 $ encode a `BS.append` encode b+hash2 a b = doubleSHA256 $ runPutS (serialize a) <> runPutS (serialize b)  -- | Computes the hash of a specific node in a Merkle tree. calcHash :: Int       -- ^ height of the node
src/Haskoin/Constants.hs view
@@ -28,10 +28,14 @@     ) where  import           Control.DeepSeq+import           Data.Binary          (Binary (..)) import           Data.ByteString      (ByteString)+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.List import           Data.Maybe-import           Data.Serialize+import           Data.Serialize       (Serialize (..)) import           Data.String import           Data.Text            (Text) import           Data.Word            (Word32, Word64, Word8)@@ -120,14 +124,22 @@     , getHalvingInterval          :: !Word32     } deriving (Eq, Generic, NFData) -instance Serialize Network where-    put net =+instance Serial Network where+    serialize net =         putWord32be $ getNetworkMagic net-    get = do+    deserialize = do         magic <- getWord32be         case find ((== magic) . getNetworkMagic) allNets of             Nothing  -> fail $ "Network magic unknown: " <> show magic             Just net -> return net++instance Binary Network where+    put = serialize+    get = deserialize++instance Serialize Network where+    put = serialize+    get = deserialize  instance Show Network where     show = getNetworkIdent
src/Haskoin/Crypto/Hash.hs view
@@ -34,17 +34,19 @@ import           Crypto.Hash             (RIPEMD160 (..), SHA1 (..),                                           SHA256 (..), SHA512 (..), hashWith) import           Crypto.MAC.HMAC         (HMAC, hmac)+import           Data.Binary             (Binary (..)) 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 qualified Data.Bytes.Get          as Get+import qualified Data.Bytes.Put          as Put+import           Data.Bytes.Serial       (Serial (..)) 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.Serialize          (Serialize (..)) import           Data.String             (IsString, fromString) import           Data.String.Conversions (cs) import           Data.Word               (Word32)@@ -55,8 +57,16 @@ -- | 'Word32' wrapped for type-safe 32-bit checksums. newtype CheckSum32 = CheckSum32     { getCheckSum32 :: Word32-    } deriving (Eq, Ord, Serialize, Show, Read, Hashable, Generic, NFData)+    } deriving (Eq, Ord, Serial, Show, Read, Hashable, Generic, NFData) +instance Serialize CheckSum32 where+    put = serialize+    get = deserialize++instance Binary CheckSum32 where+    put = serialize+    get = deserialize+ -- | Type for 512-bit hashes. newtype Hash512 = Hash512 { getHash512 :: ShortByteString }     deriving (Eq, Ord, Hashable, Generic, NFData)@@ -104,10 +114,18 @@       where         e = error "Could not decode hash from hex string" +instance Serial Hash512 where+    deserialize = Hash512 . BSS.toShort <$> Get.getByteString 64+    serialize = Put.putByteString . BSS.fromShort . getHash512+ instance Serialize Hash512 where-    get = Hash512 <$> Get.getShortByteString 64-    put = Put.putShortByteString . getHash512+    put = serialize+    get = deserialize +instance Binary Hash512 where+    put = serialize+    get = deserialize+ instance IsString Hash256 where     fromString str =         case decodeHex $ cs str of@@ -119,10 +137,18 @@       where         e = error "Could not decode hash from hex string" +instance Serial Hash256 where+    deserialize = Hash256 . BSS.toShort <$> Get.getByteString 32+    serialize = Put.putByteString . BSS.fromShort . getHash256+ instance Serialize Hash256 where-    get = Hash256 <$> Get.getShortByteString 32-    put = Put.putShortByteString . getHash256+    put = serialize+    get = deserialize +instance Binary Hash256 where+    put = serialize+    get = deserialize+ instance IsString Hash160 where     fromString str =         case decodeHex $ cs str of@@ -134,10 +160,18 @@       where         e = error "Could not decode hash from hex string" +instance Serial Hash160 where+    deserialize = Hash160 . BSS.toShort <$> Get.getByteString 20+    serialize = Put.putByteString . BSS.fromShort . getHash160+ instance Serialize Hash160 where-    get = Hash160 <$> Get.getShortByteString 20-    put = Put.putShortByteString . getHash160+    put = serialize+    get = deserialize +instance Binary Hash160 where+    put = serialize+    get = deserialize+ -- | Calculate SHA512 hash. sha512 :: ByteArrayAccess b => b -> Hash512 sha512 = Hash512 . BSS.toShort . BA.convert . hashWith SHA512@@ -169,7 +203,7 @@ -- | Computes a 32 bit checksum. checkSum32 :: ByteArrayAccess b => b -> CheckSum32 checkSum32 = fromRight (error "Could not decode bytes as CheckSum32")-             . decode+             . Get.runGetS deserialize              . BS.take 4              . BA.convert              . hashWith SHA256
src/Haskoin/Crypto/Signature.hs view
@@ -23,17 +23,21 @@  import           Control.Monad       (guard, unless, when) import           Crypto.Secp256k1+import           Data.Binary         (Binary (..)) import           Data.ByteString     (ByteString) import qualified Data.ByteString     as BS+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Maybe          (fromMaybe, isNothing)-import           Data.Serialize      as S+import           Data.Serialize      (Serialize (..)) import           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+    fromMaybe e . msg . runPutS . serialize   where     e = error "Could not convert 32-byte hash to secp256k1 message" @@ -48,7 +52,7 @@     norm = fromMaybe s (normalizeSig s)  -- | Deserialize an ECDSA signature as commonly encoded in Bitcoin.-getSig :: Get Sig+getSig :: MonadGet m => m Sig getSig = do     l <-         lookAhead $ do@@ -67,7 +71,7 @@         Nothing -> fail "Invalid signature"  -- | Serialize an ECDSA signature for Bitcoin use.-putSig :: Putter Sig+putSig :: MonadPut m => Sig -> m () putSig s = putByteString $ exportSig s  -- | Is canonical half order.
src/Haskoin/Keys/Common.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE DeriveGeneric     #-} {-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {-|@@ -40,14 +41,16 @@ import           Data.Aeson              (FromJSON, ToJSON (..), Value (String),                                           parseJSON, withText) import           Data.Aeson.Encoding     (unsafeToEncoding)+import           Data.Binary             (Binary (..)) import           Data.ByteString         (ByteString) import qualified Data.ByteString         as BS import           Data.ByteString.Builder (char7)+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Hashable import           Data.Maybe              (fromMaybe)-import           Data.Serialize          (Serialize, decode, encode, get, put)-import           Data.Serialize.Get      (getByteString)-import           Data.Serialize.Put      (putByteString)+import           Data.Serialize          (Serialize (..)) import           Data.String             (IsString, fromString) import           Data.String.Conversions (cs) import           GHC.Generics            (Generic)@@ -64,32 +67,50 @@  instance IsString PubKeyI where     fromString str =-        fromMaybe e $ eitherToMaybe . decode <=< decodeHex $ cs str+        fromMaybe e $ eitherToMaybe . runGetS deserialize <=< decodeHex $ cs str       where         e = error "Could not decode public key"  instance ToJSON PubKeyI where-    toJSON = String . encodeHex . encode-    toEncoding s = unsafeToEncoding $ char7 '"' <> hexBuilder (encode s) <> char7 '"'+    toJSON = String . encodeHex . runPutS . serialize+    toEncoding s = unsafeToEncoding $+        char7 '"' <>+        hexBuilder (runPutL (serialize s)) <>+        char7 '"'  instance FromJSON PubKeyI where     parseJSON = withText "PubKeyI" $-        maybe mzero return . (eitherToMaybe . decode =<<) . decodeHex+        maybe mzero return . (eitherToMaybe . runGetS deserialize =<<) . decodeHex -instance Serialize PubKeyI where-    get = c <|> u+instance Serial PubKeyI where+    deserialize = s >>= \case+        True  -> c+        False -> u       where+        s = lookAhead $ getWord8 >>= \case+            0x02 -> return True+            0x03 -> return True+            0x04 -> return False+            _    -> fail "Not a public key"         c = do             bs <- getByteString 33-            guard $ BS.head bs `BS.elem` BS.pack [0x02, 0x03]-            maybe mzero return $ PubKeyI <$> importPubKey bs <*> pure True+            maybe (fail "Could not decode public key") return $+                PubKeyI <$> importPubKey bs <*> pure True         u = do             bs <- getByteString 65-            guard $ BS.head bs == 0x04-            maybe mzero return $ PubKeyI <$> importPubKey bs <*> pure False+            maybe (fail "Could not decode public key") return $+                PubKeyI <$> importPubKey bs <*> pure False -    put pk = putByteString $ exportPubKey (pubKeyCompressed pk) (pubKeyPoint pk)+    serialize pk = putByteString $ exportPubKey (pubKeyCompressed pk) (pubKeyPoint pk) +instance Serialize PubKeyI where+    put = serialize+    get = deserialize++instance Binary PubKeyI where+    put = serialize+    get = deserialize+ -- | Wrap a public key from secp256k1 library adding information about compression. wrapPubKey :: Bool -> PubKey -> PubKeyI wrapPubKey c p = PubKeyI p c@@ -101,7 +122,7 @@  -- | Tweak a public key. tweakPubKey :: PubKey -> Hash256 -> Maybe PubKey-tweakPubKey p h = tweakAddPubKey p =<< tweak (encode h)+tweakPubKey p h = tweakAddPubKey p =<< tweak (runPutS (serialize h))  -- | Elliptic curve private key type with expected public key compression -- information. Compression information is stored in private key WIF formats and@@ -118,15 +139,15 @@  -- | Tweak a private key. tweakSecKey :: SecKey -> Hash256 -> Maybe SecKey-tweakSecKey key h = tweakAddSecKey key =<< tweak (encode h)+tweakSecKey key h = tweakAddSecKey key =<< tweak (runPutS (serialize h))  -- | Decode Casascius mini private keys (22 or 30 characters). fromMiniKey :: ByteString -> Maybe SecKeyI fromMiniKey bs = do     guard checkShortKey-    wrapSecKey False <$> secKey (encode (sha256 bs))+    wrapSecKey False <$> secKey (runPutS (serialize (sha256 bs)))   where-    checkHash = encode $ sha256 $ bs `BS.append` "?"+    checkHash = runPutS $ serialize $ sha256 $ bs `BS.append` "?"     checkShortKey = BS.length bs `elem` [22, 30] && BS.head checkHash == 0x00  -- | Decode private key from WIF (wallet import format) string.
src/Haskoin/Keys/Extended.hs view
@@ -111,18 +111,20 @@                                                toJSON, withText) import           Data.Aeson.Encoding     (Encoding, text) import           Data.Aeson.Types        (Parser)+import           Data.Binary             (Binary (get, put)) import           Data.Bits               (clearBit, setBit, testBit) import           Data.ByteString         (ByteString) import qualified Data.ByteString         as B+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Either             (fromRight) import           Data.Hashable import           Data.List               (foldl') import           Data.List.Split         (splitOn) import           Data.Maybe              (fromMaybe)-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.Serialize          (Serialize (..))+import qualified Data.Serialize          as S import           Data.String             (IsString, fromString) import           Data.String.Conversions (cs) import           Data.Typeable           (Typeable)@@ -165,20 +167,28 @@     , xPrvKey    :: !SecKey      -- ^ private key of this node     } deriving (Generic, Eq, Show, Read, NFData, Hashable) -instance Serialize XPrvKey where-    put k = do+instance Serial XPrvKey where+    serialize k = do         putWord8 $ xPrvDepth k         putWord32be $ xPrvParent k         putWord32be $ xPrvIndex k-        put $ xPrvChain k+        serialize $ xPrvChain k         putPadPrvKey $ xPrvKey k-    get =+    deserialize =         XPrvKey <$> getWord8                 <*> getWord32be                 <*> getWord32be-                <*> S.get+                <*> deserialize                 <*> getPadPrvKey +instance Binary XPrvKey where+    put = serialize+    get = deserialize++instance Serialize XPrvKey where+    put = serialize+    get = deserialize+ xPrvToJSON :: Network -> XPrvKey -> Value xPrvToJSON net = A.String . xPrvExport net @@ -202,20 +212,28 @@     , xPubKey    :: !PubKey    -- ^ public key of this node     } deriving (Generic, Eq, Show, Read, NFData, Hashable) -instance Serialize XPubKey where-    put k = do+instance Serial XPubKey where+    serialize k = do         putWord8 $ xPubDepth k         putWord32be $ xPubParent k         putWord32be $ xPubIndex k-        put $ xPubChain k-        put $ wrapPubKey True (xPubKey k)-    get =+        serialize $ xPubChain k+        serialize $ wrapPubKey True (xPubKey k)+    deserialize =         XPubKey <$> getWord8                 <*> getWord32be                 <*> getWord32be-                <*> S.get-                <*> (pubKeyPoint <$> S.get)+                <*> deserialize+                <*> (pubKeyPoint <$> deserialize) +instance Serialize XPubKey where+    put = serialize+    get = deserialize++instance Binary XPubKey where+    put = serialize+    get = deserialize+ -- | Decode an extended public key from a JSON string xPubFromJSON :: Network -> Value -> Parser XPubKey xPubFromJSON net =@@ -238,7 +256,7 @@     XPrvKey 0 0 0 c k   where     (p, c) = split512 $ hmac512 "Bitcoin seed" bs-    k     = fromMaybe err (secKey (encode p))+    k     = fromMaybe err (secKey (runPutS (serialize p)))     err   = throw $ DerivationException "Invalid seed"  -- | Derive an extended public key from an extended private key. This function@@ -265,8 +283,8 @@     | otherwise = error "Invalid child derivation index"   where     pK = xPubKey $ deriveXPubKey xkey-    m = B.append (exportPubKey True pK) (encode child)-    (a, c) = split512 $ hmac512 (encode $ xPrvChain xkey) m+    m = B.append (exportPubKey True pK) (runPutS (serialize child))+    (a, c) = split512 $ hmac512 (runPutS $ serialize $ xPrvChain xkey) m     k = fromMaybe err $ tweakSecKey (xPrvKey xkey) a     err = throw $ DerivationException "Invalid prvSubKey derivation" @@ -280,8 +298,8 @@         XPubKey (xPubDepth xKey + 1) (xPubFP xKey) child c pK     | otherwise = error "Invalid child derivation index"   where-    m = B.append (exportPubKey True (xPubKey xKey)) (encode child)-    (a, c) = split512 $ hmac512 (encode $ xPubChain xKey) m+    m = B.append (exportPubKey True (xPubKey xKey)) (runPutS $ serialize child)+    (a, c) = split512 $ hmac512 (runPutS $ serialize $ xPubChain xKey) m     pK = fromMaybe err $ tweakPubKey (xPubKey xKey) a     err = throw $ DerivationException "Invalid pubSubKey derivation" @@ -300,8 +318,8 @@     | otherwise = error "Invalid child derivation index"   where     i = setBit child 31-    m = B.append (bsPadPrvKey $ xPrvKey xkey) (encode i)-    (a, c) = split512 $ hmac512 (encode $ xPrvChain xkey) m+    m = B.append (bsPadPrvKey $ xPrvKey xkey) (runPutS $ serialize i)+    (a, c) = split512 $ hmac512 (runPutS $ serialize $ xPrvChain xkey) m     k = fromMaybe err $ tweakSecKey (xPrvKey xkey) a     err = throw $ DerivationException "Invalid hardSubKey derivation" @@ -331,19 +349,19 @@  -- | Computes the key identifier of an extended public key. xPubID :: XPubKey -> Hash160-xPubID = ripemd160 . encode . sha256 . exportPubKey True . xPubKey+xPubID = ripemd160 . runPutS . serialize . sha256 . exportPubKey True . xPubKey  -- | Computes the key fingerprint of an extended private key. xPrvFP :: XPrvKey -> Fingerprint xPrvFP =-    fromRight err . decode . B.take 4 . encode . xPrvID+    fromRight err . runGetS deserialize . B.take 4 . runPutS . serialize . xPrvID   where     err = error "Could not decode xPrvFP"  -- | Computes the key fingerprint of an extended public key. xPubFP :: XPubKey -> Fingerprint xPubFP =-    fromRight err . decode . B.take 4 . encode . xPubID+    fromRight err . runGetS deserialize . B.take 4 . runPutS . serialize . xPubID   where     err = error "Could not decode xPubFP" @@ -363,53 +381,53 @@  -- | Exports an extended private key to the BIP32 key export format ('Base58'). xPrvExport :: Network -> XPrvKey -> Base58-xPrvExport net = encodeBase58Check . runPut . putXPrvKey net+xPrvExport net = encodeBase58Check . runPutS . putXPrvKey net  -- | Exports an extended public key to the BIP32 key export format ('Base58'). xPubExport :: Network -> XPubKey -> Base58-xPubExport net = encodeBase58Check . runPut . putXPubKey net+xPubExport net = encodeBase58Check . runPutS . putXPubKey net  -- | 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+xPrvImport net = eitherToMaybe . runGetS (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+xPubImport net = eitherToMaybe . runGetS (getXPubKey net) <=< decodeBase58Check  -- | Export an extended private key to WIF (Wallet Import Format). xPrvWif :: Network -> XPrvKey -> Base58 xPrvWif net xkey = toWif net (wrapSecKey True (xPrvKey xkey))  -- | Parse a binary extended private key.-getXPrvKey :: Network -> Get XPrvKey+getXPrvKey :: MonadGet m => Network -> m XPrvKey getXPrvKey net = do     ver <- getWord32be     unless (ver == getExtSecretPrefix net) $ fail         "Get: Invalid version for extended private key"-    S.get+    deserialize  -- | Serialize an extended private key.-putXPrvKey :: Network -> Putter XPrvKey+putXPrvKey :: MonadPut m => Network -> XPrvKey -> m () putXPrvKey net k = do     putWord32be $ getExtSecretPrefix net-    put k+    serialize k  -- | Parse a binary extended public key.-getXPubKey :: Network -> Get XPubKey+getXPubKey :: MonadGet m => Network -> m XPubKey getXPubKey net = do     ver <- getWord32be     unless (ver == getExtPubKeyPrefix net) $ fail         "Get: Invalid version for extended public key"-    S.get+    deserialize  -- | Serialize an extended public key.-putXPubKey :: Network -> Putter XPubKey+putXPubKey :: MonadPut m => Network -> XPubKey -> m () putXPubKey net k = do     putWord32be $ getExtPubKeyPrefix net-    put k+    serialize k  {- Derivation helpers -} @@ -580,18 +598,54 @@     Deriv `compare` _      = LT     _     `compare` Deriv  = GT +instance Serial DerivPath where+    deserialize = listToPath <$> getList getWord32be+    serialize = putList putWord32be . pathToList+ instance Serialize DerivPath where-    get = listToPath <$> S.get-    put = put . pathToList+    put = serialize+    get = deserialize +instance Binary DerivPath where+    put = serialize+    get = deserialize++instance Serial HardPath where+    deserialize =+        maybe+        (fail "Could not decode hard path")+        return .+        toHard .+        listToPath =<<+        getList getWord32be+    serialize = putList putWord32be . pathToList+ instance Serialize HardPath where-    get = maybe mzero return . toHard . listToPath =<< S.get-    put = put . pathToList+    put = serialize+    get = deserialize +instance Binary HardPath where+    put = serialize+    get = deserialize++instance Serial SoftPath where+    deserialize =+        maybe+        (fail "Could not decode soft path")+        return .+        toSoft .+        listToPath =<<+        getList getWord32be+    serialize = putList putWord32be . pathToList+ instance Serialize SoftPath where-    get = maybe mzero return . toSoft . listToPath =<< S.get-    put = put . pathToList+    put = serialize+    get = deserialize +instance Binary SoftPath where+    put = serialize+    get = deserialize+ -- | Get a list of derivation indices from a derivation path. pathToList :: DerivPathI t -> [KeyIndex] pathToList =@@ -927,15 +981,18 @@ {- Utilities for extended keys -}  -- | De-serialize HDW-specific private key.-getPadPrvKey :: Get SecKey+getPadPrvKey :: MonadGet m => m SecKey getPadPrvKey = do     pad <- getWord8     unless (pad == 0x00) $ fail "Private key must be padded with 0x00"-    S.get+    bs <- getByteString 32+    case runGetS S.get bs of+        Left e  -> fail e+        Right x -> return x  -- | Serialize HDW-specific private key.-putPadPrvKey :: Putter SecKey-putPadPrvKey p = putWord8 0x00 >> S.put p+putPadPrvKey :: MonadPut m => SecKey -> m ()+putPadPrvKey p = putWord8 0x00 >> putByteString (runPutS (S.put p))  bsPadPrvKey :: SecKey -> ByteString-bsPadPrvKey = runPut . putPadPrvKey+bsPadPrvKey = runPutS . putPadPrvKey
src/Haskoin/Network/Bloom.hs view
@@ -31,18 +31,18 @@  import           Control.DeepSeq import           Control.Monad              (forM_, replicateM)+import           Data.Binary                (Binary (..)) import           Data.Bits import           Data.ByteString            (ByteString) import qualified Data.ByteString            as BS+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import qualified Data.Foldable              as F import           Data.Hash.Murmur           (murmur3) import           Data.List                  (foldl') import qualified Data.Sequence              as S-import           Data.Serialize             (Serialize, encode, get, put)-import           Data.Serialize.Get         (getByteString, getWord32le,-                                             getWord8)-import           Data.Serialize.Put         (putByteString, putWord32le,-                                             putWord8)+import           Data.Serialize             (Serialize (..)) import           Data.Word import           GHC.Generics               (Generic) import           Haskoin.Network.Common@@ -74,19 +74,27 @@     -- ^ auto-update on pay-to-pubkey or pay-to-multisig (default)     deriving (Eq, Show, Read, Generic, NFData) -instance Serialize BloomFlags where-    get = go =<< getWord8+instance Serial BloomFlags where+    deserialize = 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+    serialize f = putWord8 $ case f of         BloomUpdateNone         -> 0         BloomUpdateAll          -> 1         BloomUpdateP2PubKeyOnly -> 2 +instance Binary BloomFlags where+    get = deserialize+    put = serialize++instance Serialize BloomFlags where+    get = deserialize+    put = serialize+ -- | 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@@ -105,45 +113,72 @@     }     deriving (Eq, Show, Read, Generic, NFData) -instance Serialize BloomFilter where+instance Serial BloomFilter where -    get = BloomFilter <$> (S.fromList <$> (readDat =<< get))-                      <*> getWord32le <*> getWord32le-                      <*> get+    deserialize =+        BloomFilter+        <$> (S.fromList <$> (readDat =<< deserialize))+        <*> getWord32le+        <*> getWord32le+        <*> deserialize       where         readDat (VarInt len) = replicateM (fromIntegral len) getWord8 -    put (BloomFilter dat hashFuncs tweak flags) = do+    serialize (BloomFilter dat hashFuncs tweak flags) = do         putVarInt $ S.length dat         forM_ (F.toList dat) putWord8         putWord32le hashFuncs         putWord32le tweak-        put flags+        serialize flags +instance Binary BloomFilter where+    put = serialize+    get = deserialize++instance Serialize BloomFilter where+    put = serialize+    get = deserialize+ -- | Set a new bloom filter on the peer connection. newtype FilterLoad = FilterLoad { filterLoadBloomFilter :: BloomFilter }     deriving (Eq, Show, Read, Generic, NFData) +instance Serial FilterLoad where+    deserialize = FilterLoad <$> deserialize+    serialize (FilterLoad f) = serialize f++instance Binary FilterLoad where+    put = serialize+    get = deserialize+ instance Serialize FilterLoad where-    get = FilterLoad <$> get-    put (FilterLoad f) = put f+    put = serialize+    get = deserialize  -- | 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, Generic, NFData) -instance Serialize FilterAdd where-    get = do-        (VarInt len) <- get+instance Serial FilterAdd where+    deserialize = do+        (VarInt len) <- deserialize         dat <- getByteString $ fromIntegral len         return $ FilterAdd dat -    put (FilterAdd bs) = do+    serialize (FilterAdd bs) = do         putVarInt $ BS.length bs         putByteString bs +instance Binary FilterAdd where+    put = serialize+    get = deserialize +instance Serialize FilterAdd where+    put = serialize+    get = deserialize++ -- | 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@@ -235,14 +270,14 @@             (BloomUpdateAll, _) -> bloomInsert bf outpoint             _ -> error "Error Updating Bloom Filter with relevant outpoint"       where-        outpoint = encode $ OutPoint {outPointHash = h, outPointIndex = id'}+        outpoint = runPutS $ serialize $ OutPoint {outPointHash = h, outPointIndex = id'}         scriptType = (\s -> isPayPK s || isPayMulSig s) scriptOut         -- Encodes a scriptOutput so it can be checked agains the Bloom Filter     encodeScriptOut :: ScriptOutput -> ByteString-    encodeScriptOut (PayMulSig outputMuSig _) = encode outputMuSig-    encodeScriptOut (PayWitnessScriptHash scriptHash) = encode scriptHash-    encodeScriptOut (DataCarrier getOutputDat) = encode getOutputDat-    encodeScriptOut outputHash = (encode . getOutputHash) outputHash+    encodeScriptOut (PayMulSig outputMuSig _) = runPutS $ serialize outputMuSig+    encodeScriptOut (PayWitnessScriptHash scriptHash) = runPutS $ serialize scriptHash+    encodeScriptOut (DataCarrier getOutputDat) = runPutS $ serialize getOutputDat+    encodeScriptOut outputHash = (runPutS . serialize . getOutputHash) outputHash  -- | Returns True if the filter is empty (all bytes set to 0x00) isBloomEmpty :: BloomFilter -> Bool
src/Haskoin/Network/Common.hs view
@@ -47,11 +47,15 @@  import           Control.DeepSeq import           Control.Monad           (forM_, liftM2, replicateM, unless)+import           Data.Binary             (Binary (..)) import           Data.Bits               (shiftL) import           Data.ByteString         (ByteString) import qualified Data.ByteString         as B import           Data.ByteString.Char8   as C (replicate)-import           Data.Serialize          as S+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial+import           Data.Serialize          (Serialize (..)) import           Data.String import           Data.String.Conversions (cs) import           Data.Word               (Word32, Word64)@@ -71,17 +75,25 @@          }     deriving (Eq, Show, Generic, NFData) -instance Serialize Addr where+instance Serial Addr where -    get = Addr <$> (repList =<< S.get)+    deserialize = Addr <$> (repList =<< deserialize)       where         repList (VarInt c) = replicateM (fromIntegral c) action-        action             = liftM2 (,) getWord32le S.get+        action             = liftM2 (,) getWord32le deserialize -    put (Addr xs) = do+    serialize (Addr xs) = do         putVarInt $ length xs-        forM_ xs $ \(a,b) -> putWord32le a >> put b+        forM_ xs $ \(a,b) -> putWord32le a >> serialize b +instance Binary Addr where+    get = deserialize+    put = serialize++instance Serialize Addr where+    get = deserialize+    put = serialize+ -- | 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.@@ -93,9 +105,17 @@           , alertSignature :: !VarString           } deriving (Eq, Show, Read, Generic, NFData) +instance Serial Alert where+    deserialize = Alert <$> deserialize <*> deserialize+    serialize (Alert p s) = serialize p >> serialize s++instance Binary Alert where+    put = serialize+    get = deserialize+ instance Serialize Alert where-    get = Alert <$> S.get <*> S.get-    put (Alert p s) = put p >> put s+    put = serialize+    get = deserialize  -- | 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'@@ -109,16 +129,24 @@               getDataList :: [InvVector]             } deriving (Eq, Show, Generic, NFData) -instance Serialize GetData where+instance Serial GetData where -    get = GetData <$> (repList =<< S.get)+    deserialize = GetData <$> (repList =<< deserialize)       where-        repList (VarInt c) = replicateM (fromIntegral c) S.get+        repList (VarInt c) = replicateM (fromIntegral c) deserialize -    put (GetData xs) = do+    serialize (GetData xs) = do         putVarInt $ length xs-        forM_ xs put+        forM_ xs serialize +instance Binary GetData where+    get = deserialize+    put = serialize++instance Serialize GetData where+    get = deserialize+    put = serialize+ -- | '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.@@ -128,16 +156,24 @@           invList :: [InvVector]         } deriving (Eq, Show, Generic, NFData) -instance Serialize Inv where+instance Serial Inv where -    get = Inv <$> (repList =<< S.get)+    deserialize = Inv <$> (repList =<< deserialize)       where-        repList (VarInt c) = replicateM (fromIntegral c) S.get+        repList (VarInt c) = replicateM (fromIntegral c) deserialize -    put (Inv xs) = do+    serialize (Inv xs) = do         putVarInt $ length xs-        forM_ xs put+        forM_ xs serialize +instance Binary Inv where+    get = deserialize+    put = serialize++instance Serialize Inv where+    get = deserialize+    put = serialize+ -- | Data type identifying the type of an inventory vector. SegWit types are -- only used in 'GetData' messages, not 'Inv'. data InvType@@ -150,8 +186,8 @@     | InvWitnessMerkleBlock -- ^ segwit filtere block     deriving (Eq, Show, Read, Generic, NFData) -instance Serialize InvType where-    get = go =<< getWord32le+instance Serial InvType where+    deserialize = go =<< getWord32le       where         go x =             case x of@@ -164,7 +200,7 @@                     | x == 1 `shiftL` 30 + 2 -> return InvWitnessBlock                     | x == 1 `shiftL` 30 + 3 -> return InvWitnessMerkleBlock                     | otherwise -> fail "bitcoinGet InvType: Invalid Type"-    put x =+    serialize x =         putWord32le $         case x of             InvError              -> 0@@ -175,6 +211,14 @@             InvWitnessBlock       -> 1 `shiftL` 30 + 2             InvWitnessMerkleBlock -> 1 `shiftL` 30 + 3 +instance Binary InvType where+    get = deserialize+    put = serialize++instance Serialize InvType where+    get = deserialize+    put = serialize+ -- | 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.@@ -186,17 +230,33 @@               , invHash :: !Hash256               } deriving (Eq, Show, Generic, NFData) +instance Serial InvVector where+    deserialize = InvVector <$> deserialize <*> deserialize+    serialize (InvVector t h) = serialize t >> serialize h++instance Binary InvVector where+    get = deserialize+    put = serialize+ instance Serialize InvVector where-    get = InvVector <$> S.get <*> S.get-    put (InvVector t h) = put t >> put h+    get = deserialize+    put = serialize  newtype HostAddress =     HostAddress ByteString     deriving (Eq, Show, Ord, Generic, NFData) +instance Serial HostAddress where+    serialize (HostAddress bs) = putByteString bs+    deserialize = HostAddress <$> getByteString 18++instance Binary HostAddress where+    get = deserialize+    put = serialize+ instance Serialize HostAddress where-    put (HostAddress bs) = putByteString bs-    get = HostAddress <$> getByteString 18+    get = deserialize+    put = serialize  -- | Data type describing a bitcoin network address. Addresses are stored in -- IPv6 format. IPv4 addresses are mapped to IPv6 using IPv4 mapped IPv6@@ -210,14 +270,14 @@  hostToSockAddr :: HostAddress -> SockAddr hostToSockAddr (HostAddress bs) =-    case runGet getSockAddr bs of+    case runGetS getSockAddr bs of         Left e  -> error e         Right x -> x  sockToHostAddress :: SockAddr -> HostAddress-sockToHostAddress = HostAddress . runPut . putSockAddr+sockToHostAddress = HostAddress . runPutS . putSockAddr -putSockAddr :: SockAddr -> Put+putSockAddr :: MonadPut m => SockAddr -> m () putSockAddr (SockAddrInet6 p _ (a, b, c, d) _) = do     putWord32be a     putWord32be b@@ -234,7 +294,7 @@  putSockAddr _ = error "Invalid address type" -getSockAddr :: Get SockAddr+getSockAddr :: MonadGet m => m SockAddr getSockAddr = do     a <- getWord32be     b <- getWord32be@@ -249,9 +309,17 @@             p <- getWord16be             return $ SockAddrInet6 (fromIntegral p) 0 (a, b, c, d) 0 +instance Serial NetworkAddress where+    deserialize = NetworkAddress <$> getWord64le <*> deserialize+    serialize (NetworkAddress s a) = putWord64le s >> serialize a++instance Binary NetworkAddress where+    get = deserialize+    put = serialize+ instance Serialize NetworkAddress where-    get = NetworkAddress <$> getWord64le <*> S.get-    put (NetworkAddress s a) = putWord64le s >> put a+    get = deserialize+    put = serialize  -- | 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,@@ -262,16 +330,24 @@                notFoundList :: [InvVector]              } deriving (Eq, Show, Generic, NFData) -instance Serialize NotFound where+instance Serial NotFound where -    get = NotFound <$> (repList =<< S.get)+    deserialize = NotFound <$> (repList =<< deserialize)       where-        repList (VarInt c) = replicateM (fromIntegral c) S.get+        repList (VarInt c) = replicateM (fromIntegral c) deserialize -    put (NotFound xs) = do+    serialize (NotFound xs) = do         putVarInt $ length xs-        forM_ xs put+        forM_ xs serialize +instance Binary NotFound where+    get = deserialize+    put = serialize++instance Serialize NotFound where+    get = deserialize+    put = serialize+ -- | A 'Ping' message is sent to bitcoin peers to check if a connection is still -- open. newtype Ping =@@ -287,13 +363,29 @@            pongNonce :: Word64          } deriving (Eq, Show, Read, Generic, NFData) +instance Serial Ping where+    deserialize = Ping <$> getWord64le+    serialize (Ping n) = putWord64le n++instance Serial Pong where+    deserialize = Pong <$> getWord64le+    serialize (Pong n) = putWord64le n++instance Binary Ping where+    get = deserialize+    put = serialize++instance Binary Pong where+    get = deserialize+    put = serialize+ instance Serialize Ping where-    get = Ping <$> getWord64le-    put (Ping n) = putWord64le n+    get = deserialize+    put = serialize  instance Serialize Pong where-    get = Pong <$> getWord64le-    put (Pong n) = putWord64le n+    get = deserialize+    put = serialize  -- | The 'Reject' message is sent when messages are rejected by a peer. data Reject =@@ -320,9 +412,10 @@     | RejectCheckpoint     deriving (Eq, Show, Read, Generic, NFData) -instance Serialize RejectCode where+instance Serial RejectCode where -    get = getWord8 >>= \code -> case code of+    deserialize =+        getWord8 >>= \code -> case code of         0x01 -> return RejectMalformed         0x10 -> return RejectInvalid         0x11 -> return RejectObsolete@@ -332,11 +425,11 @@         0x42 -> return RejectInsufficientFee         0x43 -> return RejectCheckpoint         _    -> fail $ unwords-            [ "Reject get: Invalid code"-            , show code-            ]+                [ "Reject get: Invalid code"+                , show code+                ] -    put code = putWord8 $ case code of+    serialize code = putWord8 $ case code of         RejectMalformed       -> 0x01         RejectInvalid         -> 0x10         RejectObsolete        -> 0x11@@ -346,42 +439,61 @@         RejectInsufficientFee -> 0x42         RejectCheckpoint      -> 0x43 +instance Binary RejectCode where+    put = serialize+    get = deserialize++instance Serialize RejectCode where+    put = serialize+    get = deserialize+ -- | 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) ->-            Reject (stringToCommand bs) <$> S.get <*> S.get <*> maybeData+instance Serial Reject where+    deserialize =+        deserialize >>= \(VarString bs) ->+            Reject (stringToCommand bs)+            <$> deserialize+            <*> deserialize+            <*> maybeData       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+    serialize (Reject cmd code reason dat) = do+        serialize $ VarString $ commandToString cmd+        serialize code+        serialize reason         unless (B.null dat) $ putByteString dat +instance Binary Reject where+    put = serialize+    get = deserialize++instance Serialize Reject where+    put = serialize+    get = deserialize+ -- | 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, Generic, NFData) -instance Serialize VarInt where+instance Serial VarInt where -    get = VarInt <$> ( getWord8 >>= go )+    deserialize = VarInt <$> ( getWord8 >>= go )       where         go 0xff = getWord64le         go 0xfe = fromIntegral <$> getWord32le         go 0xfd = fromIntegral <$> getWord16le         go x    = fromIntegral <$> return x -    put (VarInt x)+    serialize (VarInt x)         | x < 0xfd =             putWord8 $ fromIntegral x         | x <= 0xffff = do@@ -394,23 +506,39 @@             putWord8 0xff             putWord64le x -putVarInt :: Integral a => a -> Put-putVarInt = put . VarInt . fromIntegral+instance Binary VarInt where+    put = serialize+    get = deserialize +instance Serialize VarInt where+    put = serialize+    get = deserialize++putVarInt :: (MonadPut m, Integral a) => a -> m ()+putVarInt = serialize . VarInt . fromIntegral+ -- | Data type for serialization of variable-length strings. newtype VarString = VarString { getVarString :: ByteString }     deriving (Eq, Show, Read, Generic, NFData) -instance Serialize VarString where+instance Serial VarString where -    get = VarString <$> (readBS =<< S.get)+    deserialize = VarString <$> (readBS =<< deserialize)       where         readBS (VarInt len) = getByteString (fromIntegral len) -    put (VarString bs) = do+    serialize (VarString bs) = do         putVarInt $ B.length bs         putByteString bs +instance Binary VarString where+    put = serialize+    get = deserialize++instance Serialize VarString where+    put = serialize+    get = deserialize+ -- | 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.@@ -436,40 +564,48 @@             , relay       :: !Bool             } deriving (Eq, Show, Generic, NFData) -instance Serialize Version where+instance Serial Version where -    get = Version <$> getWord32le-                  <*> getWord64le-                  <*> getWord64le-                  <*> S.get-                  <*> S.get-                  <*> getWord64le-                  <*> S.get-                  <*> getWord32le-                  <*> (go =<< isEmpty)+    deserialize = Version <$> getWord32le+                          <*> getWord64le+                          <*> getWord64le+                          <*> deserialize+                          <*> deserialize+                          <*> getWord64le+                          <*> deserialize+                          <*> getWord32le+                          <*> (go =<< isEmpty)       where         go True  = return True         go False = getBool -    put (Version v s t ar as n ua sh r) = do+    serialize (Version v s t ar as n ua sh r) = do         putWord32le v         putWord64le s         putWord64le t-        put         ar-        put         as+        serialize   ar+        serialize   as         putWord64le n-        put         ua+        serialize   ua         putWord32le sh         putBool     r +instance Binary Version where+    put = serialize+    get = deserialize++instance Serialize Version where+    put = serialize+    get = deserialize+ -- | 0x00 is 'False', anything else is 'True'.-getBool :: Get Bool+getBool :: MonadGet m => m Bool getBool = go =<< getWord8   where     go 0 = return False     go _ = return True -putBool :: Bool -> Put+putBool :: MonadPut m => Bool -> m () putBool True  = putWord8 1 putBool False = putWord8 0 @@ -512,13 +648,21 @@         String str <- lexP         return (stringToCommand (cs str)) -instance Serialize MessageCommand where-    get = go <$> getByteString 12+instance Serial MessageCommand where+    deserialize = go <$> getByteString 12       where         go bs =             let str = unpackCommand bs              in stringToCommand str-    put mc = putByteString $ packCommand $ commandToString mc+    serialize mc = putByteString $ packCommand $ commandToString mc++instance Binary MessageCommand where+    put = serialize+    get = deserialize++instance Serialize MessageCommand where+    put = serialize+    get = deserialize  instance IsString MessageCommand where     fromString str = stringToCommand (cs str)
src/Haskoin/Network/Message.hs view
@@ -21,13 +21,13 @@  import           Control.DeepSeq import           Control.Monad              (unless)+import           Data.Binary                (Binary (..)) import           Data.ByteString            (ByteString) 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.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial+import           Data.Serialize             (Serialize (..)) import           Data.Word                  (Word32) import           GHC.Generics               (Generic) import           Haskoin.Block.Common@@ -51,19 +51,29 @@     , headChecksum    :: !CheckSum32     } deriving (Eq, Show, Generic, NFData) -instance Serialize MessageHeader where+instance Serial MessageHeader where -    get = MessageHeader <$> getWord32be-                        <*> get-                        <*> getWord32le-                        <*> get+    deserialize =+        MessageHeader+        <$> getWord32be+        <*> deserialize+        <*> getWord32le+        <*> deserialize -    put (MessageHeader m c l chk) = do+    serialize (MessageHeader m c l chk) = do         putWord32be m-        put         c+        serialize   c         putWord32le l-        put         chk+        serialize   chk +instance Binary MessageHeader where+    put = serialize+    get = deserialize++instance Serialize MessageHeader where+    put = serialize+    get = deserialize+ -- | 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@@ -124,9 +134,9 @@ msgType (MOther c _)     = MCOther c  -- | Deserializer for network messages.-getMessage :: Network -> Get Message+getMessage :: MonadGet m => Network -> m Message getMessage net = do-    (MessageHeader mgc cmd len chk) <- get+    (MessageHeader mgc cmd len chk) <- deserialize     bs <- lookAhead $ getByteString $ fromIntegral len     unless         (mgc == getNetworkMagic net)@@ -135,28 +145,30 @@         (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-                 MCOther c     -> MOther c <$> getByteString (fromIntegral len)-                 _             -> fail $ "get: command " ++ show cmd ++-                                         " should not carry a payload"+        then do+             bs <- ensure (fromIntegral len)+             let f = case cmd of+                     MCVersion     -> MVersion <$> deserialize+                     MCAddr        -> MAddr <$> deserialize+                     MCInv         -> MInv <$> deserialize+                     MCGetData     -> MGetData <$> deserialize+                     MCNotFound    -> MNotFound <$> deserialize+                     MCGetBlocks   -> MGetBlocks <$> deserialize+                     MCGetHeaders  -> MGetHeaders <$> deserialize+                     MCTx          -> MTx <$> deserialize+                     MCBlock       -> MBlock <$> deserialize+                     MCMerkleBlock -> MMerkleBlock <$> deserialize+                     MCHeaders     -> MHeaders <$> deserialize+                     MCFilterLoad  -> MFilterLoad <$> deserialize+                     MCFilterAdd   -> MFilterAdd <$> deserialize+                     MCPing        -> MPing <$> deserialize+                     MCPong        -> MPong <$> deserialize+                     MCAlert       -> MAlert <$> deserialize+                     MCReject      -> MReject <$> deserialize+                     MCOther c     -> MOther c <$> getByteString (fromIntegral len)+                     _             -> fail $ "get: command " ++ show cmd +++                                            " should not carry a payload"+             either fail return (runGetS f bs)         else case cmd of                  MCGetAddr     -> return MGetAddr                  MCVerAck      -> return MVerAck@@ -167,35 +179,35 @@                                          " is expected to carry a payload"  -- | Serializer for network messages.-putMessage :: Network -> Putter Message+putMessage :: MonadPut m => Network -> Message -> m () 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)-                MOther c p     -> (MCOther c, p)+            MVersion m     -> (MCVersion, runPutS $ serialize m)+            MVerAck        -> (MCVerAck, BS.empty)+            MAddr m        -> (MCAddr, runPutS $ serialize m)+            MInv m         -> (MCInv, runPutS $ serialize m)+            MGetData m     -> (MCGetData, runPutS $ serialize m)+            MNotFound m    -> (MCNotFound, runPutS $ serialize m)+            MGetBlocks m   -> (MCGetBlocks, runPutS $ serialize m)+            MGetHeaders m  -> (MCGetHeaders, runPutS $ serialize m)+            MTx m          -> (MCTx, runPutS $ serialize m)+            MBlock m       -> (MCBlock, runPutS $ serialize m)+            MMerkleBlock m -> (MCMerkleBlock, runPutS $ serialize m)+            MHeaders m     -> (MCHeaders, runPutS $ serialize m)+            MGetAddr       -> (MCGetAddr, BS.empty)+            MFilterLoad m  -> (MCFilterLoad, runPutS $ serialize m)+            MFilterAdd m   -> (MCFilterAdd, runPutS $ serialize m)+            MFilterClear   -> (MCFilterClear, BS.empty)+            MPing m        -> (MCPing, runPutS $ serialize m)+            MPong m        -> (MCPong, runPutS $ serialize m)+            MAlert m       -> (MCAlert, runPutS $ serialize m)+            MMempool       -> (MCMempool, BS.empty)+            MReject m      -> (MCReject, runPutS $ serialize m)+            MSendHeaders   -> (MCSendHeaders, BS.empty)+            MOther c p     -> (MCOther c, p)         chk = checkSum32 payload         len = fromIntegral $ BS.length payload         header = MessageHeader (getNetworkMagic net) cmd len chk-    put header+    serialize header     putByteString payload
src/Haskoin/Script/Common.hs view
@@ -24,12 +24,16 @@  import           Control.DeepSeq import           Control.Monad-import           Data.ByteString (ByteString)-import qualified Data.ByteString as B+import           Data.Binary       (Binary (..))+import           Data.ByteString   (ByteString)+import qualified Data.ByteString   as B+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Hashable-import           Data.Serialize  as S-import           Data.Word       (Word8)-import           GHC.Generics    (Generic)+import           Data.Serialize    (Serialize (..))+import           Data.Word         (Word8)+import           GHC.Generics      (Generic)  -- | Data type representing a transaction script. Scripts are defined as lists -- of script operators 'ScriptOp'. Scripts are used to:@@ -47,18 +51,26 @@            }     deriving (Eq, Show, Read, Generic, Hashable, NFData) -instance Serialize Script where-    get =+instance Serial Script where+    deserialize =         Script <$> getScriptOps       where         getScriptOps = do             empty <- isEmpty             if empty                 then return []-                else (:) <$> get <*> getScriptOps+                else (:) <$> deserialize <*> getScriptOps -    put (Script ops) = forM_ ops put+    serialize (Script ops) = forM_ ops serialize +instance Binary Script where+    put = serialize+    get = deserialize++instance Serialize Script where+    put = serialize+    get = deserialize+ -- | Data type representing the type of an OP_PUSHDATA opcode. data PushDataType     =@@ -203,8 +215,8 @@     | OP_INVALIDOPCODE !Word8     deriving (Show, Read, Eq, Generic, Hashable, NFData) -instance Serialize ScriptOp where-    get = go =<< (fromIntegral <$> getWord8)+instance Serial ScriptOp where+    deserialize = go =<< (fromIntegral <$> getWord8)       where         go op             | op == 0x00 = return OP_0@@ -359,7 +371,7 @@              | otherwise = return $ OP_INVALIDOPCODE op -    put op = case op of+    serialize op = case op of          (OP_PUSHDATA payload optype)-> do             let len = B.length payload@@ -523,7 +535,14 @@         -- Bitcoin Cash May 2020 hard fork         OP_REVERSEBYTES      -> putWord8 0xbc +instance Binary ScriptOp where+    put = serialize+    get = deserialize +instance Serialize ScriptOp where+    put = serialize+    get = deserialize+ -- | Check whether opcode is only data. isPushOp :: ScriptOp -> Bool isPushOp op = case op of@@ -565,7 +584,13 @@     | i `elem` [1 .. 16] = op     | otherwise = err   where-    op = either (const err) id . S.decode . B.singleton . fromIntegral $ i + 0x50+    op = either+        (const err)+        id .+        runGetS deserialize .+        B.singleton .+        fromIntegral $+        i + 0x50     err = error $ "intToScriptOp: Invalid integer " ++ show i  -- | Decode 'ScriptOp' @[OP_1 .. OP_16]@ to integers @[1 .. 16]@. This functions@@ -575,4 +600,4 @@     | res `elem` [1..16] = return res     | otherwise          = Left $ "scriptOpToInt: invalid opcode " ++ show s   where-    res = fromIntegral (B.head $ S.encode s) - 0x50+    res = fromIntegral (B.head $ runPutS $ serialize s) - 0x50
src/Haskoin/Script/SigHash.hs view
@@ -41,16 +41,18 @@ import qualified Data.Aeson                 as J import           Data.Bits import qualified Data.ByteString            as BS+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Hashable import           Data.Maybe import           Data.Scientific-import           Data.Serialize import           Data.Word import           GHC.Generics               (Generic) import           Haskoin.Constants+import           Haskoin.Crypto import           Haskoin.Crypto.Hash import           Haskoin.Network.Common-import           Haskoin.Crypto import           Haskoin.Script.Common import           Haskoin.Transaction.Common import           Haskoin.Util@@ -207,8 +209,8 @@             let newTx = Tx (txVersion tx) newIn newOut [] (txLockTime tx)             return $                 doubleSHA256 $-                runPut $ do-                    put newTx+                runPutS $ do+                    serialize newTx                     putWord32le $ fromIntegral sh   where     fout = Script $ filter (/= OP_CODESEPARATOR) $ scriptOps out@@ -218,13 +220,13 @@ buildInputs :: [TxIn] -> Script -> Int -> SigHash -> [TxIn] buildInputs txins out i sh     | hasAnyoneCanPayFlag sh =-        [ (txins !! i) { scriptInput = encode out } ]+        [ (txins !! i) { scriptInput = runPutS $ serialize 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 }+        updateIndex i emptyIn $ \ti -> ti { scriptInput = runPutS $ serialize out }     noSeq ti j =         if i == j         then ti@@ -251,35 +253,35 @@     -> SigHash -- ^ what to sign     -> Hash256 -- ^ hash to be signed txSigHashForkId net tx out v i sh =-    doubleSHA256 . runPut $ do+    doubleSHA256 . runPutS $ do         putWord32le $ txVersion tx-        put hashPrevouts-        put hashSequence-        put $ prevOutput $ txIn tx !! i+        serialize hashPrevouts+        serialize hashSequence+        serialize $ prevOutput $ txIn tx !! i         putScript out         putWord64le v         putWord32le $ txInSequence $ txIn tx !! i-        put hashOutputs+        serialize hashOutputs         putWord32le $ txLockTime tx         putWord32le $ fromIntegral $ sigHashAddNetworkId net sh   where     hashPrevouts         | not $ hasAnyoneCanPayFlag sh =-            doubleSHA256 $ runPut $ mapM_ (put . prevOutput) $ txIn tx+            doubleSHA256 $ runPutS $ mapM_ (serialize . prevOutput) $ txIn tx         | otherwise = zeros     hashSequence         | not (hasAnyoneCanPayFlag sh) &&               not (isSigHashSingle sh) && not (isSigHashNone sh) =-            doubleSHA256 $ runPut $ mapM_ (putWord32le . txInSequence) $ txIn tx+            doubleSHA256 $ runPutS $ mapM_ (putWord32le . txInSequence) $ txIn tx         | otherwise = zeros     hashOutputs         | not (isSigHashSingle sh) && not (isSigHashNone sh) =-            doubleSHA256 $ runPut $ mapM_ put $ txOut tx+            doubleSHA256 $ runPutS $ mapM_ serialize $ txOut tx         | isSigHashSingle sh && i < length (txOut tx) =-            doubleSHA256 $ encode $ txOut tx !! i+            doubleSHA256 $ runPutS $ serialize $ txOut tx !! i         | otherwise = zeros     putScript s = do-        let encodedScript = encode s+        let encodedScript = runPutS $ serialize s         putVarInt $ BS.length encodedScript         putByteString encodedScript     zeros :: Hash256@@ -302,7 +304,7 @@ encodeTxSig :: TxSignature -> BS.ByteString encodeTxSig TxSignatureEmpty = error "Can not encode an empty signature" encodeTxSig (TxSignature sig (SigHash n)) =-    runPut $ putSig sig >> putWord8 (fromIntegral n)+    runPutS $ putSig sig >> putWord8 (fromIntegral n)  -- | Deserialize a 'TxSignature'. decodeTxSig :: Network -> BS.ByteString -> Either String TxSignature
src/Haskoin/Script/Standard.hs view
@@ -50,11 +50,13 @@ import qualified Data.Aeson.Encoding    as A import           Data.ByteString        (ByteString) import qualified Data.ByteString        as BS+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Function          (on) import           Data.Hashable import           Data.List              (sortBy)-import           Data.Maybe             (fromJust, isJust)-import           Data.Serialize         as S+import           Data.Maybe             (fromJust, isJust, isNothing) import           Data.Word              (Word8) import           GHC.Generics           (Generic) import           Haskoin.Constants@@ -145,17 +147,19 @@ decodeOutput :: Script -> Either String ScriptOutput decodeOutput s = case scriptOps s of     -- Pay to PubKey-    [OP_PUSHDATA bs _, OP_CHECKSIG] -> PayPK <$> S.decode bs+    [OP_PUSHDATA bs _, OP_CHECKSIG] -> PayPK <$> runGetS deserialize bs     -- Pay to PubKey Hash     [OP_DUP, OP_HASH160, OP_PUSHDATA bs _, OP_EQUALVERIFY, OP_CHECKSIG] ->-        PayPKHash <$> S.decode bs+        PayPKHash <$> runGetS deserialize bs     -- Pay to Script Hash     [OP_HASH160, OP_PUSHDATA bs _, OP_EQUAL] ->-        PayScriptHash <$> S.decode  bs+        PayScriptHash <$> runGetS deserialize  bs     -- Pay to Witness     [OP_0, OP_PUSHDATA bs OPCODE]-      | BS.length bs == 20 -> PayWitnessPKHash     <$> S.decode bs-      | BS.length bs == 32 -> PayWitnessScriptHash <$> S.decode bs+      | BS.length bs == 20 -> PayWitnessPKHash     <$> runGetS deserialize bs+      | BS.length bs == 32 -> PayWitnessScriptHash <$> runGetS deserialize bs+      | BS.length bs /= 20 && BS.length bs /= 32 ->+            Left "Version 0 segwit program must be 20 or 32 bytes long"     -- Other Witness     [ver, OP_PUSHDATA bs _]       | isJust (opWitnessVersion ver)@@ -204,23 +208,23 @@ opWitnessVersion OP_14 = Just 14 opWitnessVersion OP_15 = Just 15 opWitnessVersion OP_16 = Just 16-opWitnessVersion _ = Nothing+opWitnessVersion _     = Nothing   -- | Similar to 'decodeOutput' but decodes from a 'ByteString'. decodeOutputBS :: ByteString -> Either String ScriptOutput-decodeOutputBS = decodeOutput <=< S.decode+decodeOutputBS = decodeOutput <=< runGetS deserialize  -- | 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]+    (PayPK k) -> [opPushData $ runPutS $ serialize k, OP_CHECKSIG]     -- Pay to PubKey Hash Address     (PayPKHash h) ->         [ OP_DUP         , OP_HASH160-        , opPushData $ S.encode h+        , opPushData $ runPutS $ serialize h         , OP_EQUALVERIFY, OP_CHECKSIG         ]     -- Pay to MultiSig Keys@@ -228,17 +232,17 @@       | r <= length ps ->         let opM = intToScriptOp r             opN = intToScriptOp $ length ps-            keys = map (opPushData . S.encode) ps+            keys = map (opPushData . runPutS . serialize) 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]+        [ OP_HASH160, opPushData $ runPutS $ serialize h, OP_EQUAL]     -- Pay to Witness PubKey Hash Address     (PayWitnessPKHash h) ->-        [ OP_0, opPushData $ S.encode h ]+        [ OP_0, opPushData $ runPutS $ serialize h ]     (PayWitnessScriptHash h) ->-        [ OP_0, opPushData $ S.encode h ]+        [ OP_0, opPushData $ runPutS $ serialize h ]     (PayWitness v h) ->         [ case witnessVersionOp v of               Nothing -> error "encodeOutput: invalid witness version"@@ -249,15 +253,15 @@  -- | Similar to 'encodeOutput' but encodes to a ByteString encodeOutputBS :: ScriptOutput -> ByteString-encodeOutputBS = S.encode . encodeOutput+encodeOutputBS = runPutS . serialize . encodeOutput  -- | Encode script as pay-to-script-hash script toP2SH :: Script -> ScriptOutput-toP2SH = PayScriptHash . addressHash . S.encode+toP2SH = PayScriptHash . addressHash . runPutS . serialize  -- | Encode script as a pay-to-witness-script-hash script toP2WSH :: Script -> ScriptOutput-toP2WSH = PayWitnessScriptHash . sha256 . S.encode+toP2WSH = PayWitnessScriptHash . sha256 . runPutS . serialize  -- | Match @[OP_N, PubKey1, ..., PubKeyM, OP_M, OP_CHECKMULTISIG]@ matchPayMulSig :: Script -> Either String ScriptOutput@@ -269,7 +273,7 @@             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 (OP_PUSHDATA bs _:xs) = liftM2 (:) (runGetS deserialize bs) (go xs)     go []                    = return []     go  _                    = Left "matchPayMulSig: invalid multisig opcode" @@ -277,8 +281,8 @@ -- 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"+    PayMulSig keys r -> PayMulSig (sortBy (compare `on` (runPutS . serialize)) keys) r+    _                -> error "Can only call orderMulSig on PayMulSig scripts"  -- | Data type describing standard transaction input scripts. Input scripts -- provide the signing data required to unlock the coins of the output they are@@ -347,7 +351,7 @@     matchPK [op] = SpendPK <$> f op     matchPK _    = Nothing     matchPKHash [op, OP_PUSHDATA pub _] =-        SpendPKHash <$> f op <*> eitherToMaybe (decode pub)+        SpendPKHash <$> f op <*> eitherToMaybe (runGetS deserialize pub)     matchPKHash _ = Nothing     matchMulSig (x:xs) = do         guard $ x == OP_0@@ -379,7 +383,7 @@ -- | Like 'decodeInput' but decodes directly from a serialized script -- 'ByteString'. decodeInputBS :: Network -> ByteString -> Either String ScriptInput-decodeInputBS net = decodeInput net <=< decode+decodeInputBS net = decodeInput net <=< runGetS deserialize  -- | Encode a standard input into a script. encodeInput :: ScriptInput -> Script@@ -391,7 +395,7 @@ -- | Similar to 'encodeInput' but encodes directly to a serialized script -- 'ByteString'. encodeInputBS :: ScriptInput -> ByteString-encodeInputBS = encode . encodeInput+encodeInputBS = runPutS . serialize . encodeInput  -- | Encode a standard 'SimpleInput' into opcodes as an input 'Script'. encodeSimpleInput :: SimpleInput -> Script@@ -399,7 +403,7 @@     Script $     case s of         SpendPK ts       -> [f ts]-        SpendPKHash ts p -> [f ts, opPushData $ encode p]+        SpendPKHash ts p -> [f ts, opPushData $ runPutS $ serialize p]         SpendMulSig xs   -> OP_0 : map f xs   where     f TxSignatureEmpty = OP_0
src/Haskoin/Transaction/Builder.hs view
@@ -49,13 +49,15 @@ import           Control.Monad.Identity           (runIdentity) import           Crypto.Secp256k1 import qualified Data.ByteString                  as B+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Conduit                     (ConduitT, Void, await,                                                    runConduit, (.|)) import           Data.Conduit.List                (sourceList) import           Data.Either                      (fromRight) import           Data.List                        (nub) import           Data.Maybe                       (catMaybes, fromJust, isJust)-import           Data.Serialize                   (decode, encode) import           Data.String.Conversions          (cs) import           Data.Text                        (Text) import           Data.Word                        (Word64)@@ -219,8 +221,20 @@ guessTxSize pki msi pkout msout =     8 + inpLen + inp + outLen + out   where-    inpLen = B.length $ encode $ VarInt $ fromIntegral $ length msi + pki-    outLen = B.length $ encode $ VarInt $ fromIntegral $ pkout + msout+    inpLen =+        B.length .+        runPutS .+        serialize .+        VarInt .+        fromIntegral $+        length msi + pki+    outLen =+        B.length .+        runPutS .+        serialize .+        VarInt .+        fromIntegral $+        pkout + msout     inp = pki * 148 + sum (map guessMSSize msi)              -- (20: hash160) + (5: opcodes) +              -- (1: script len) + (8: Word64)@@ -234,12 +248,14 @@ guessMSSize :: (Int,Int) -> Int guessMSSize (m, n)     -- OutPoint (36) + Sequence (4) + Script- = 40 + fromIntegral (B.length $ encode $ VarInt $ fromIntegral scp) + scp+ = 40 ++   fromIntegral (B.length $ runPutS . serialize $ VarInt $ fromIntegral scp) ++   scp     -- OP_M + n*PubKey + OP_N + OP_CHECKMULTISIG   where     rdm =         fromIntegral $-        B.length $ encode $ opPushData $ B.replicate (n * 34 + 3) 0+        B.length $ runPutS $ serialize $ opPushData $ B.replicate (n * 34 + 3) 0     -- Redeem + m*sig + OP_0     scp = rdm + m * 73 + 1 @@ -414,9 +430,9 @@     wp so = decodeWitnessInput net =<< viewWitnessProgram net so ws      nestedScriptOutput :: Either String ScriptOutput-    nestedScriptOutput = scriptOps <$> decode inp >>= \case+    nestedScriptOutput = scriptOps <$> runGetS deserialize inp >>= \case         [OP_PUSHDATA bs _] -> decodeOutputBS bs-        _ -> Left "nestedScriptOutput: not a nested output"+        _                  -> Left "nestedScriptOutput: not a nested output"      verifyLegacyInput :: ScriptOutput -> ScriptInput -> Bool     verifyLegacyInput so si = case (so, si) of@@ -443,7 +459,7 @@             verifyHashSig (theTxSigHash so sh $ Just rdm') sig (pubKeyPoint pub)         (PayWitnessScriptHash h, Just rdm'@(PayPKHash kh), SpendPKHash (TxSignature sig sh) pub) ->             payToWitnessScriptAddress rdm' == p2wshAddr h &&-            addressHash (encode pub) == kh &&+            addressHash (runPutS (serialize pub)) == kh &&             verifyHashSig (theTxSigHash so sh $ Just rdm') sig (pubKeyPoint pub)         (PayWitnessScriptHash h, Just rdm'@(PayMulSig pubs r), SpendMulSig sigs) ->             payToWitnessScriptAddress rdm' == p2wshAddr h &&
src/Haskoin/Transaction/Builder/Sign.hs view
@@ -28,12 +28,14 @@ import           Data.Aeson                 (FromJSON, ToJSON (..), object,                                              pairs, parseJSON, withObject, (.:),                                              (.:?), (.=))+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Either                (rights) import           Data.Hashable              (Hashable) import           Data.List                  (find, nub) import           Data.Maybe                 (catMaybes, fromMaybe, mapMaybe,                                              maybeToList)-import qualified Data.Serialize             as S import           Data.Word                  (Word64) import           GHC.Generics               (Generic) import           Haskoin.Address            (getAddrHash160, pubKeyAddr)@@ -125,7 +127,7 @@               }   where     f si x = x {scriptInput = encodeInputBS si}-    g so' x = x {scriptInput = S.encode . opPushData $ encodeOutputBS so'}+    g so' x = x {scriptInput = runPutS . serialize . opPushData $ encodeOutputBS so'}     txis = txIn tx     nextTxIn so' si         | isSegwit so' && nest = updateIndex i txis (g so')
src/Haskoin/Transaction/Common.hs view
@@ -31,15 +31,20 @@ import           Control.Applicative     ((<|>)) import           Control.DeepSeq import           Control.Monad           (forM_, guard, liftM2, mzero,-                                          replicateM, (<=<))+                                          replicateM, unless, when, (<=<)) import           Data.Aeson              as A import           Data.Aeson.Encoding     (unsafeToEncoding)+import           Data.Binary             (Binary (..)) import           Data.ByteString         (ByteString) import qualified Data.ByteString         as B import           Data.ByteString.Builder (char7)+import qualified Data.ByteString.Lazy    as BL+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Hashable           (Hashable) import           Data.Maybe              (fromMaybe)-import           Data.Serialize          as S+import           Data.Serialize          (Serialize (..)) import           Data.String             (IsString, fromString) import           Data.String.Conversions (cs) import           Data.Text               (Text)@@ -52,8 +57,16 @@  -- | Transaction id: hash of transaction excluding witness data. newtype TxHash = TxHash { getTxHash :: Hash256 }-    deriving (Eq, Ord, Generic, Hashable, Serialize, NFData)+    deriving (Eq, Ord, Generic, Hashable, Serial, NFData) +instance Serialize TxHash where+    put = serialize+    get = deserialize++instance Binary TxHash where+    put = serialize+    get = deserialize+ instance Show TxHash where     showsPrec _ = shows . txHashToHex @@ -74,24 +87,28 @@ instance ToJSON TxHash where     toJSON = A.String . txHashToHex     toEncoding h =-        unsafeToEncoding $ char7 '"' <> hexBuilder (B.reverse (S.encode h)) <> char7 '"'+        unsafeToEncoding $+        char7 '"' <>+        hexBuilder (BL.reverse (runPutL (serialize h))) <>+        char7 '"'  -- | Transaction hash excluding signatures. nosigTxHash :: Tx -> TxHash nosigTxHash tx =-    TxHash $ doubleSHA256 $ S.encode tx { txIn = map clearInput $ txIn tx }+    TxHash $ doubleSHA256 $ runPutS $+    serialize 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))+txHashToHex (TxHash h) = encodeHex (B.reverse (runPutS (serialize 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)+    h <- either (const Nothing) Just (runGetS deserialize bs)     return $ TxHash h  -- | Witness stack for SegWit transactions.@@ -117,36 +134,45 @@  -- | Compute transaction hash. txHash :: Tx -> TxHash-txHash tx = TxHash (doubleSHA256 (S.encode tx {txWitness = []}))+txHash tx = TxHash . doubleSHA256 . runPutS $ serialize tx {txWitness = []}  instance IsString Tx where     fromString =-        fromMaybe e . (eitherToMaybe . S.decode <=< decodeHex) . cs+        fromMaybe e . (eitherToMaybe . runGetS deserialize <=< decodeHex) . cs       where         e = error "Could not read transaction from hex string" -instance Serialize Tx where-    get = parseWitnessTx <|> parseLegacyTx-    put tx+instance Serial Tx where+    deserialize =+        isWitnessTx >>= \w -> if w then parseWitnessTx else parseLegacyTx+    serialize tx         | null (txWitness tx) = putLegacyTx tx         | otherwise = putWitnessTx tx -putInOut :: Tx -> Put+instance Binary Tx where+    put = serialize+    get = deserialize++instance Serialize Tx where+    put = serialize+    get = deserialize++putInOut :: MonadPut m => Tx -> m () putInOut tx = do     putVarInt $ length (txIn tx)-    forM_ (txIn tx) put+    forM_ (txIn tx) serialize     putVarInt $ length (txOut tx)-    forM_ (txOut tx) put+    forM_ (txOut tx) serialize  -- | Non-SegWit transaction serializer.-putLegacyTx :: Tx -> Put+putLegacyTx :: MonadPut m => Tx -> m () putLegacyTx tx = do     putWord32le (txVersion tx)     putInOut tx     putWord32le (txLockTime tx)  -- | Witness transaciton serializer.-putWitnessTx :: Tx -> Put+putWitnessTx :: MonadPut m => Tx -> m () putWitnessTx tx = do     putWord32le (txVersion tx)     putWord8 0x00@@ -155,49 +181,61 @@     putWitnessData (txWitness tx)     putWord32le (txLockTime tx) +isWitnessTx :: MonadGet m => m Bool+isWitnessTx = lookAhead $ do+    _ <- getWord32le+    m <- getWord8+    f <- getWord8+    return (m == 0x00 && f == 0x01)+ -- | Non-SegWit transaction deseralizer.-parseLegacyTx :: Get Tx+parseLegacyTx :: MonadGet m => m Tx parseLegacyTx = do     v <- getWord32le-    is <- replicateList =<< S.get-    os <- replicateList =<< S.get+    is <- replicateList =<< deserialize+    os <- replicateList =<< deserialize+    when (length is == 0x00 && length os == 0x01) $ fail "Witness transaction"     l <- getWord32le     return         Tx-        {txVersion = v, txIn = is, txOut = os, txWitness = [], txLockTime = l}+        { txVersion = v+        , txIn = is+        , txOut = os+        , txWitness = []+        , txLockTime = l+        }   where-    replicateList (VarInt c) = replicateM (fromIntegral c) S.get+    replicateList (VarInt c) = replicateM (fromIntegral c) deserialize  -- | Witness transaction deserializer.-parseWitnessTx :: Get Tx+parseWitnessTx :: MonadGet m => m Tx parseWitnessTx = do     v <- getWord32le     m <- getWord8     f <- getWord8-    guard $ m == 0x00-    guard $ f == 0x01-    is <- replicateList =<< S.get-    os <- replicateList =<< S.get+    unless (m == 0x00 && f == 0x01) $ fail "Not a witness transaction"+    is <- replicateList =<< deserialize+    os <- replicateList =<< deserialize     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+    replicateList (VarInt c) = replicateM (fromIntegral c) deserialize  -- | Witness data deserializer. Requires count of inputs.-parseWitnessData :: Int -> Get WitnessData+parseWitnessData :: MonadGet m => Int -> m WitnessData parseWitnessData n = replicateM n parseWitnessStack   where     parseWitnessStack = do-        VarInt i <- S.get+        VarInt i <- deserialize         replicateM (fromIntegral i) parseWitnessStackItem     parseWitnessStackItem = do-        VarInt i <- S.get+        VarInt i <- deserialize         getByteString $ fromIntegral i  -- | Witness data serializer.-putWitnessData :: WitnessData -> Put+putWitnessData :: MonadPut m => WitnessData -> m () putWitnessData = mapM_ putWitnessStack   where     putWitnessStack ws = do@@ -246,18 +284,26 @@          , txInSequence :: !Word32          } deriving (Eq, Show, Read, Ord, Generic, Hashable, NFData) -instance Serialize TxIn where-    get =-        TxIn <$> S.get <*> (readBS =<< S.get) <*> getWord32le+instance Serial TxIn where+    deserialize =+        TxIn <$> deserialize <*> (readBS =<< deserialize) <*> getWord32le       where         readBS (VarInt len) = getByteString $ fromIntegral len -    put (TxIn o s q) = do-        put o+    serialize (TxIn o s q) = do+        serialize o         putVarInt $ B.length s         putByteString s         putWord32le q +instance Binary TxIn where+    get = deserialize+    put = serialize++instance Serialize TxIn where+    get = deserialize+    put = serialize+ instance FromJSON TxIn where     parseJSON =         withObject "TxIn" $ \o ->@@ -288,17 +334,25 @@           , scriptOutput :: !ByteString           } deriving (Eq, Show, Read, Ord, Generic, Hashable, NFData) -instance Serialize TxOut where-    get = do+instance Serial TxOut where+    deserialize = do         val <- getWord64le-        (VarInt len) <- S.get+        VarInt len <- deserialize         TxOut val <$> getByteString (fromIntegral len) -    put (TxOut o s) = do+    serialize (TxOut o s) = do         putWord64le o         putVarInt $ B.length s         putByteString s +instance Binary TxOut where+    put = serialize+    get = deserialize++instance Serialize TxOut where+    put = serialize+    get = deserialize+ instance FromJSON TxOut where     parseJSON =         withObject "TxOut" $ \o ->@@ -319,11 +373,19 @@     , outPointIndex :: !Word32     } deriving (Show, Read, Eq, Ord, Generic, Hashable, NFData) -instance Serialize OutPoint where-    get = do-        (h,i) <- liftM2 (,) S.get getWord32le+instance Serial OutPoint where+    deserialize = do+        (h,i) <- liftM2 (,) deserialize getWord32le         return $ OutPoint h i-    put (OutPoint h i) = put h >> putWord32le i+    serialize (OutPoint h i) = serialize h >> putWord32le i++instance Binary OutPoint where+    put = serialize+    get = deserialize++instance Serialize OutPoint where+    put = serialize+    get = deserialize  instance FromJSON OutPoint where     parseJSON =
src/Haskoin/Transaction/Partial.hs view
@@ -35,12 +35,16 @@ import           Control.Monad              (guard, replicateM, void) import           Data.ByteString            (ByteString) import qualified Data.ByteString            as B-import           Data.Hashable              (Hashable)+import           Data.Bytes.Get             (runGetS)+import           Data.Bytes.Put             (runPutS)+import           Data.Bytes.Serial          (Serial (..)) import           Data.HashMap.Strict        (HashMap) import qualified Data.HashMap.Strict        as HashMap+import           Data.Hashable              (Hashable) import           Data.List                  (foldl') import           Data.Maybe                 (fromMaybe, isJust)-import           Data.Serialize             as S+import           Data.Serialize             (Get, Put, Serialize)+import qualified Data.Serialize             as S import           GHC.Generics               (Generic) import           GHC.Word                   (Word32, Word8) import           Haskoin.Address            (Address (..), pubKeyAddr)@@ -64,7 +68,8 @@ -- output per output in the unsigned transaction. The inputs and outputs in the -- 'PartiallySignedTransaction' line up by index with the inputs and outputs in -- the unsigned transaction.-data PartiallySignedTransaction = PartiallySignedTransaction+data PartiallySignedTransaction =+    PartiallySignedTransaction     { unsignedTransaction :: Tx     , globalUnknown       :: UnknownMap     , inputs              :: [Input]@@ -100,8 +105,9 @@  instance NFData Output --- | A map of raw PSBT keys to byte strings for extra data. The 'keyType' field cannot overlap with any of the reserved--- 'keyType' fields specified in the PSBT specification.+-- | A map of raw PSBT keys to byte strings for extra data. The 'keyType' field+-- cannot overlap with any of the reserved 'keyType' fields specified in the+-- PSBT specification. newtype UnknownMap = UnknownMap { unknownMap :: HashMap Key ByteString }     deriving (Show, Eq, Semigroup, Monoid, Generic) @@ -117,8 +123,11 @@  instance Hashable Key --- | Take two 'PartiallySignedTransaction's and merge them. The 'unsignedTransaction' field in both must be the same.-merge :: PartiallySignedTransaction -> PartiallySignedTransaction -> Maybe PartiallySignedTransaction+-- | Take two 'PartiallySignedTransaction's and merge them. The+-- 'unsignedTransaction' field in both must be the same.+merge :: PartiallySignedTransaction+      -> PartiallySignedTransaction+      -> Maybe PartiallySignedTransaction merge psbt1 psbt2     | unsignedTransaction psbt1 == unsignedTransaction psbt2     = Just $ psbt1@@ -130,38 +139,68 @@  mergeInput :: Input -> Input -> Input mergeInput a b = Input-    { nonWitnessUtxo = if isJust witUtx then Nothing else nonWitnessUtxo a <|> nonWitnessUtxo b-    , witnessUtxo = witUtx-    , sigHashType = sigHashType a <|> sigHashType b-    , partialSigs = partialSigs a <> partialSigs b-    , inputHDKeypaths = inputHDKeypaths a <> inputHDKeypaths b-    , inputUnknown = inputUnknown a <> inputUnknown b-    , inputRedeemScript = inputRedeemScript a <|> inputRedeemScript b-    , inputWitnessScript = inputWitnessScript a <|> inputWitnessScript b-    , finalScriptSig = finalScriptSig a <|> finalScriptSig b-    , finalScriptWitness = finalScriptWitness a <|> finalScriptWitness b+    { nonWitnessUtxo =+            if isJust witUtx+            then Nothing+            else nonWitnessUtxo a <|> nonWitnessUtxo b+    , witnessUtxo =+            witUtx+    , sigHashType =+            sigHashType a <|> sigHashType b+    , partialSigs =+            partialSigs a <> partialSigs b+    , inputHDKeypaths =+            inputHDKeypaths a <> inputHDKeypaths b+    , inputUnknown =+            inputUnknown a <> inputUnknown b+    , inputRedeemScript =+            inputRedeemScript a <|> inputRedeemScript b+    , inputWitnessScript =+            inputWitnessScript a <|> inputWitnessScript b+    , finalScriptSig =+            finalScriptSig a <|> finalScriptSig b+    , finalScriptWitness =+            finalScriptWitness a <|> finalScriptWitness b     }   where     witUtx = witnessUtxo a <|> witnessUtxo b  mergeOutput :: Output -> Output -> Output mergeOutput a b = Output-    { outputRedeemScript = outputRedeemScript a <|> outputRedeemScript b-    , outputWitnessScript = outputWitnessScript a <|> outputWitnessScript b-    , outputHDKeypaths = outputHDKeypaths a <> outputHDKeypaths b-    , outputUnknown = outputUnknown a <> outputUnknown b+    { outputRedeemScript =+            outputRedeemScript a <|> outputRedeemScript b+    , outputWitnessScript =+            outputWitnessScript a <|> outputWitnessScript b+    , outputHDKeypaths =+            outputHDKeypaths a <> outputHDKeypaths b+    , outputUnknown =+            outputUnknown a <> outputUnknown b     }  -- | Take partial signatures from all of the 'Input's and finalize the signature.-complete :: PartiallySignedTransaction -> PartiallySignedTransaction-complete psbt = psbt { inputs = map (completeInput . analyzeInputs) (indexed $ inputs psbt) }+complete :: PartiallySignedTransaction+         -> PartiallySignedTransaction+complete psbt =+    psbt+    {+        inputs = map+                 (completeInput . analyzeInputs)+                 (indexed $ inputs psbt)+    }   where-    analyzeInputs (i, input) = (outputScript =<< witnessUtxo input <|> nonWitScript, input)+    analyzeInputs (i, input) =+        (,)+        (outputScript =<< witnessUtxo input <|> nonWitScript)+        input       where         nonWitScript = getPrevOut i =<< nonWitnessUtxo input      getPrevOut i tx =-       (txOut tx !!?) . fromIntegral . outPointIndex . prevOutput =<< txIn (unsignedTransaction psbt) !!? i+       (txOut tx !!?) .+       fromIntegral .+       outPointIndex .+       prevOutput =<<+       txIn (unsignedTransaction psbt) !!? i     xs !!? i = lookup i $ indexed xs      outputScript = eitherToMaybe . decodeOutputBS . scriptOutput@@ -173,65 +212,127 @@     indexed = zip [0..]  completeSig :: Input -> ScriptOutput -> Input+ completeSig input (PayPK k) =-    input { finalScriptSig = eitherToMaybe . S.decode =<< HashMap.lookup k (partialSigs input) }+    input+    { finalScriptSig =+            eitherToMaybe . runGetS deserialize =<<+            HashMap.lookup k (partialSigs input)+    }+ completeSig input (PayPKHash h)-    | [(k, sig)] <- HashMap.toList $ partialSigs input-    , PubKeyAddress h == pubKeyAddr k-    = input { finalScriptSig = Just $ Script [opPushData sig, opPushData (S.encode k)] }-completeSig input (PayMulSig pubKeys m) | length sigs >= m = input { finalScriptSig = finalSig }+    | [(k, sig)] <- HashMap.toList (partialSigs input)+    , PubKeyAddress h == pubKeyAddr k =+            input+            {+                finalScriptSig =+                    Just $+                    Script+                    [+                        opPushData sig,+                        opPushData (runPutS (serialize k))+                    ]+            }++completeSig input (PayMulSig pubKeys m)+    | length sigs >= m =+          input { finalScriptSig = finalSig }   where     sigs = collectSigs m pubKeys input-    finalSig = Script . (OP_0 :) . (map opPushData sigs <>) . pure . opPushData . S.encode <$> inputRedeemScript input+    finalSig =+        Script .+        (OP_0 :) .+        (map opPushData sigs <>) .+        pure . opPushData . runPutS . serialize <$>+        inputRedeemScript input+ completeSig input (PayScriptHash h)     | Just rdmScript <- inputRedeemScript input     , PayScriptHash h == toP2SH rdmScript     , Right decodedScript <- decodeOutput rdmScript-    , not (isPayScriptHash decodedScript)-    = completeSig input decodedScript+    , not (isPayScriptHash decodedScript) =+            completeSig input decodedScript+ completeSig input (PayWitnessPKHash h)-    | [(k, sig)] <- HashMap.toList $ partialSigs input-    , PubKeyAddress h == pubKeyAddr k-    = input { finalScriptWitness = Just [sig, S.encode k]-            , finalScriptSig = Script . pure . opPushData . S.encode <$> inputRedeemScript input+    | [(k, sig)] <- HashMap.toList (partialSigs input)+    , PubKeyAddress h == pubKeyAddr k =+            input+            {+                finalScriptWitness =+                    Just [sig, runPutS $ serialize k],+                finalScriptSig =+                    Script . pure . opPushData . runPutS . serialize <$>+                    inputRedeemScript input             } completeSig input (PayWitnessScriptHash h)     | Just witScript <- inputWitnessScript input     , PayWitnessScriptHash h == toP2WSH witScript-    , Right decodedScript <- decodeOutput witScript-    = completeWitnessSig input decodedScript+    , Right decodedScript <- decodeOutput witScript =+            completeWitnessSig input decodedScript+ completeSig input _ = input  completeWitnessSig :: Input -> ScriptOutput -> Input-completeWitnessSig input script@(PayMulSig pubKeys m) | length sigs >= m = input-    { finalScriptWitness = Just finalWit-    , finalScriptSig = finalSig-    }+completeWitnessSig input script@(PayMulSig pubKeys m)+    | length sigs >= m =+          input+          {+              finalScriptWitness = Just finalWit,+              finalScriptSig = finalSig+          }   where     sigs = collectSigs m pubKeys input-    finalSig = Script . pure . opPushData . S.encode <$> inputRedeemScript input+    finalSig = Script . pure . opPushData . runPutS . serialize <$>+               inputRedeemScript input     finalWit = mempty : sigs <> [encodeOutputBS script]+ completeWitnessSig input _ = input  collectSigs :: Int -> [PubKeyI] -> Input -> [ByteString]-collectSigs m pubKeys input = take m . reverse $ foldl' lookupKey [] pubKeys+collectSigs m pubKeys input =+    take m . reverse $ foldl' lookupKey [] pubKeys   where-    lookupKey sigs key = maybe sigs (:sigs) $ HashMap.lookup key (partialSigs input)+    lookupKey sigs key =+        maybe sigs (: sigs) $+        HashMap.lookup key (partialSigs input) --- | Take a finalized 'PartiallySignedTransaction' and produce the signed final transaction.  You may need to call--- 'complete' on the 'PartiallySignedTransaction' before producing the final transaction.+-- | Take a finalized 'PartiallySignedTransaction' and produce the signed final+-- transaction. You may need to call 'complete' on the+-- 'PartiallySignedTransaction' before producing the final transaction. finalTransaction :: PartiallySignedTransaction -> Tx-finalTransaction psbt = setInputs . foldl' finalizeInput ([], []) $ zip (txIn tx) (inputs psbt)+finalTransaction psbt =+    setInputs .+    foldl' finalizeInput ([], []) $+    zip (txIn tx) (inputs psbt)   where     tx = unsignedTransaction psbt-    hasWitness = any (isJust . finalScriptWitness) (inputs psbt)-    setInputs (ins, witData) = tx { txIn = reverse ins, txWitness = if hasWitness then reverse witData else [] }-    finalizeInput (ins, witData) (txInput, psbtInput) = maybe finalWitness finalScript $ finalScriptSig psbtInput+    hasWitness =+        any+        (isJust . finalScriptWitness)+        (inputs psbt)+    setInputs (ins, witData) =+        tx+        {+            txIn = reverse ins,+            txWitness = if hasWitness then reverse witData else []+        }+    finalizeInput (ins, witData) (txInput, psbtInput) =+        maybe finalWitness finalScript $+        finalScriptSig psbtInput       where-        finalScript script = (txInput { scriptInput = encode script }:ins, []:witData)-        finalWitness = (ins, fromMaybe [] (finalScriptWitness psbtInput):witData)+        finalScript script =+            (+                txInput { scriptInput = runPutS $ serialize script } : ins,+                [] : witData+            )+        finalWitness =+            (+                ins,+                fromMaybe [] (finalScriptWitness psbtInput) : witData+            ) --- | Take an unsigned transaction and produce an empty 'PartiallySignedTransaction'+-- | Take an unsigned transaction and produce an empty+-- 'PartiallySignedTransaction' emptyPSBT :: Tx -> PartiallySignedTransaction emptyPSBT tx = PartiallySignedTransaction     { unsignedTransaction = tx@@ -251,120 +352,190 @@  instance Serialize PartiallySignedTransaction where     get = do-        magic <- getBytes 4+        magic <- S.getBytes 4         guard $ magic == "psbt"-        headerSep <- getWord8+        headerSep <- S.getWord8         guard $ headerSep == 0xff -        keySize <- getWord8+        keySize <- S.getWord8         guard $ keySize == 1-        globalUnsignedTxType <- getWord8+        globalUnsignedTxType <- S.getWord8         guard $ globalUnsignedTxType == 0x00-        unsignedTransaction <- getSizedBytes+        unsignedTransaction <- getSizedBytes deserialize         guard $ all (B.null . scriptInput) (txIn unsignedTransaction)         guard $ null (txWitness unsignedTransaction) -        globalUnknown <- get-        globalEnd <- getWord8+        globalUnknown <- S.get+        globalEnd <- S.getWord8         guard $ globalEnd == 0x00 -        inputs <- replicateM (length $ txIn unsignedTransaction) get-        outputs <- replicateM (length $ txOut unsignedTransaction) get+        inputs <-+            replicateM+            (length (txIn unsignedTransaction))+            S.get+        outputs <-+            replicateM+            (length (txOut unsignedTransaction))+            S.get -        return PartiallySignedTransaction { unsignedTransaction, globalUnknown, inputs, outputs }+        return+            PartiallySignedTransaction+            {+                unsignedTransaction,+                globalUnknown,+                inputs,+                outputs+            } -    put PartiallySignedTransaction{ unsignedTransaction, globalUnknown, inputs, outputs } = do-        putByteString "psbt"-        putWord8 0xff -- Header separator+    put PartiallySignedTransaction+        {+            unsignedTransaction,+            globalUnknown,+            inputs,+            outputs+        } = do+        S.putByteString "psbt"+        S.putWord8 0xff -- Header separator -        putWord8 0x01 -- Key size-        putWord8 0x00 -- Unsigned Transaction type-        putSizedBytes unsignedTransaction-        put globalUnknown-        putWord8 0x00 -- Global end+        S.putWord8 0x01 -- Key size+        S.putWord8 0x00 -- Unsigned Transaction type+        putSizedBytes $ serialize unsignedTransaction+        S.put globalUnknown+        S.putWord8 0x00 -- Global end -        mapM_ put inputs-        mapM_ put outputs+        mapM_ S.put inputs+        mapM_ S.put outputs  instance Serialize Key where     get = do-        VarInt keySize <- get+        VarInt keySize <- deserialize         guard $ keySize > 0-        t <- getWord8-        k <- getBytes (fromIntegral keySize - 1)+        t <- S.getWord8+        k <- S.getBytes (fromIntegral keySize - 1)         return (Key t k)      put (Key t k) = do         putVarInt $ 1 + B.length k-        putWord8 t-        putByteString k+        S.putWord8 t+        S.putByteString k  instance Serialize UnknownMap where     get = go HashMap.empty       where         getItem m = do-            k <- get-            VarString v <- get+            k <- S.get+            VarString v <- deserialize             go $ HashMap.insert k v m         go m = do-            isEnd <- lookAhead getWord8+            isEnd <- S.lookAhead S.getWord8             if isEnd == 0x00                 then return (UnknownMap m)                 else getItem m -    put (UnknownMap m) = void $ HashMap.traverseWithKey (\k v -> put k >> put (VarString v)) m+    put (UnknownMap m) =+        void $+        HashMap.traverseWithKey+        (\k v -> S.put k >> serialize (VarString v))+        m  instance Serialize Input where-    get = getMap getInputItem setInputUnknown emptyInput+    get =+        getMap getInputItem setInputUnknown emptyInput       where-        setInputUnknown f input = input { inputUnknown = UnknownMap $ f (unknownMap $ inputUnknown input) }+        setInputUnknown f input =+            input+            {+                inputUnknown =+                    UnknownMap (f (unknownMap (inputUnknown input)))+            } -    put Input { nonWitnessUtxo, witnessUtxo, partialSigs, sigHashType-                  , inputRedeemScript, inputWitnessScript, inputHDKeypaths-                  , finalScriptSig, finalScriptWitness, inputUnknown-                  } = do-        whenJust (putKeyValue InNonWitnessUtxo) nonWitnessUtxo-        whenJust (putKeyValue InWitnessUtxo) witnessUtxo+    put Input+        {+            nonWitnessUtxo,+            witnessUtxo,+            partialSigs,+            sigHashType,+            inputRedeemScript,+            inputWitnessScript,+            inputHDKeypaths,+            finalScriptSig,+            finalScriptWitness,+            inputUnknown+        } = do+        whenJust (putKeyValue InNonWitnessUtxo . serialize)+            nonWitnessUtxo+        whenJust (putKeyValue InWitnessUtxo . serialize)+            witnessUtxo         putPartialSig partialSigs-        whenJust putSigHash sigHashType-        whenJust (putKeyValue InRedeemScript) inputRedeemScript-        whenJust (putKeyValue InWitnessScript) inputWitnessScript+        whenJust putSigHash+            sigHashType+        whenJust (putKeyValue InRedeemScript . serialize)+            inputRedeemScript+        whenJust (putKeyValue InWitnessScript . serialize)+            inputWitnessScript         putHDPath InBIP32Derivation inputHDKeypaths-        whenJust (putKeyValue InFinalScriptSig) finalScriptSig-        whenJust (putKeyValue InFinalScriptWitness) finalScriptWitness-        put inputUnknown-        putWord8 0x00+        whenJust (putKeyValue InFinalScriptSig . serialize)+            finalScriptSig+        whenJust (putKeyValue InFinalScriptWitness . serialize)+            finalScriptWitness+        S.put inputUnknown+        S.putWord8 0x00       where-        putPartialSig = putPubKeyMap InPartialSig . fmap VarString+        putPartialSig =+            putPubKeyMap serialize InPartialSig . fmap VarString         putSigHash sigHash = do             putKey InSigHashType-            putWord8 0x04-            putWord32le (fromIntegral sigHash)+            S.putWord8 0x04+            S.putWord32le (fromIntegral sigHash)  instance Serialize Output where     get = getMap getOutputItem setOutputUnknown emptyOutput       where-        setOutputUnknown f output = output { outputUnknown = UnknownMap $ f (unknownMap $ outputUnknown output) }+        setOutputUnknown f output =+            output+            {+                outputUnknown =+                    UnknownMap (f (unknownMap (outputUnknown output)))+            } -    put Output{ outputRedeemScript, outputWitnessScript, outputHDKeypaths, outputUnknown } = do-        whenJust (putKeyValue OutRedeemScript) outputRedeemScript-        whenJust (putKeyValue OutWitnessScript) outputWitnessScript-        putHDPath OutBIP32Derivation outputHDKeypaths-        put outputUnknown-        putWord8 0x00+    put Output+        {+            outputRedeemScript,+            outputWitnessScript,+            outputHDKeypaths,+            outputUnknown+        } = do+        whenJust (putKeyValue OutRedeemScript . serialize)+            outputRedeemScript+        whenJust (putKeyValue OutWitnessScript . serialize)+            outputWitnessScript+        putHDPath OutBIP32Derivation+            outputHDKeypaths+        S.put outputUnknown+        S.putWord8 0x00 -putSizedBytes :: Serialize a => a -> Put-putSizedBytes a = putVarInt (B.length bs) >> putByteString bs-  where bs = encode a+putSizedBytes :: Put -> Put+putSizedBytes f = do+    putVarInt (B.length bs)+    S.putByteString bs+  where+    bs = S.runPut f -getSizedBytes :: Serialize a => Get a-getSizedBytes = getNested (fromIntegral . getVarInt <$> get) get+getSizedBytes :: Get a -> Get a+getSizedBytes f =+    S.getNested+    (fromIntegral . getVarInt <$> deserialize)+    f -putKeyValue :: (Enum t, Serialize v) => t -> v -> Put-putKeyValue t v = putKey t >> putSizedBytes v+putKeyValue :: Enum t => t -> Put -> Put+putKeyValue t v = do+    putKey t+    putSizedBytes v  putKey :: Enum t => t -> Put-putKey t = putVarInt (1 :: Word8) >> putWord8 (enumWord8 t)+putKey t = do+    putVarInt (1 :: Word8)+    S.putWord8 (enumWord8 t)  getMap :: (Bounded t, Enum t)        => (Int -> a -> t -> Get a)@@ -372,16 +543,17 @@        -> a -> Get a getMap getMapItem setUnknown = go   where-    getItem keySize m (Right t) = getMapItem (fromIntegral keySize - 1) m t >>= go+    getItem keySize m (Right t) =+        getMapItem (fromIntegral keySize - 1) m t >>= go     getItem keySize m (Left t)  = do-        k <- getBytes (fromIntegral keySize - 1)-        VarString v <- get+        k <- S.getBytes (fromIntegral keySize - 1)+        VarString v <- deserialize         go $ setUnknown (HashMap.insert (Key t k) v) m     go m = do-        keySize <- getVarInt <$> get+        keySize <- getVarInt <$> deserialize         if keySize == 0             then return m-            else getItem keySize m =<< (word8Enum <$> getWord8)+            else getItem keySize m =<< (word8Enum <$> S.getWord8)  data InputType     = InNonWitnessUtxo@@ -406,89 +578,124 @@ instance NFData OutputType  getInputItem :: Int -> Input -> InputType -> Get Input+ getInputItem 0 input@Input{nonWitnessUtxo = Nothing} InNonWitnessUtxo = do-    utxo <- getSizedBytes-    return $ input { nonWitnessUtxo = Just utxo }+    utxo <- getSizedBytes deserialize+    return input { nonWitnessUtxo = Just utxo }+ getInputItem 0 input@Input{witnessUtxo = Nothing} InWitnessUtxo = do-    utxo <- getSizedBytes-    return $ input { witnessUtxo = Just utxo }+    utxo <- getSizedBytes deserialize+    return input { witnessUtxo = Just utxo }+ getInputItem keySize input InPartialSig = do     (k, v) <- getPartialSig-    return $ input { partialSigs = HashMap.insert k v (partialSigs input) }+    return+        input+        {+            partialSigs = HashMap.insert k v (partialSigs input)+        }   where-    getPartialSig = (,) <$> isolate keySize get <*> (getVarString <$> get)+    getPartialSig =+        (,)+        <$> S.isolate keySize deserialize+        <*> (getVarString <$> deserialize)+ getInputItem 0 input@Input{sigHashType = Nothing} InSigHashType = do-    VarInt size <- get+    VarInt size <- deserialize     guard $ size == 0x04-    sigHash <- fromIntegral <$> getWord32le+    sigHash <- fromIntegral <$> S.getWord32le     return $ input { sigHashType = Just sigHash }+ getInputItem 0 input@Input{inputRedeemScript = Nothing} InRedeemScript = do-    script <- getSizedBytes+    script <- getSizedBytes deserialize     return $ input { inputRedeemScript = Just script }+ getInputItem 0 input@Input{inputWitnessScript = Nothing} InWitnessScript = do-    script <- getSizedBytes+    script <- getSizedBytes deserialize     return $ input { inputWitnessScript = Just script }+ getInputItem keySize input InBIP32Derivation = do     (k, v) <- getHDPath keySize-    return $ input { inputHDKeypaths = HashMap.insert k v (inputHDKeypaths input) }+    return+        input+        {+            inputHDKeypaths = HashMap.insert k v (inputHDKeypaths input)+        }+ getInputItem 0 input@Input{finalScriptSig = Nothing} InFinalScriptSig = do-    script <- getSizedBytes+    script <- getSizedBytes deserialize     return $ input { finalScriptSig = Just script }+ getInputItem 0 input@Input{finalScriptWitness = Nothing} InFinalScriptWitness = do     scripts <- map getVarString <$> getVarIntList     return $ input { finalScriptWitness = Just scripts }   where     getVarIntList = do-        VarInt n <- get-        replicateM (fromIntegral n) get+        VarInt n <- deserialize+        replicateM (fromIntegral n) deserialize+ getInputItem keySize input inputType = fail $     "Incorrect key size for input item or item already existed: " <>     show (keySize, input, inputType)  getOutputItem :: Int -> Output -> OutputType -> Get Output+ getOutputItem 0 output@Output{outputRedeemScript = Nothing} OutRedeemScript = do-    script <- getSizedBytes+    script <- getSizedBytes deserialize     return $ output { outputRedeemScript = Just script }+ getOutputItem 0 output@Output{outputWitnessScript = Nothing} OutWitnessScript = do-    script <- getSizedBytes+    script <- getSizedBytes deserialize     return $ output { outputWitnessScript = Just script }+ getOutputItem keySize output OutBIP32Derivation = do     (k, v) <- getHDPath keySize     return $ output { outputHDKeypaths = HashMap.insert k v (outputHDKeypaths output) }+ getOutputItem keySize output outputType = fail $     "Incorrect key size for output item or item already existed: " <>     show (keySize, output, outputType)  getHDPath :: Int -> Get (PubKeyI, (Fingerprint, [KeyIndex]))-getHDPath keySize = (,) <$> isolate keySize get <*> (unPSBTHDPath <$> get)+getHDPath keySize =+    (,)+    <$> S.isolate keySize deserialize+    <*> (unPSBTHDPath <$> S.get)  putHDPath :: Enum t => t -> HashMap PubKeyI (Fingerprint, [KeyIndex]) -> Put-putHDPath t = putPubKeyMap t . fmap PSBTHDPath+putHDPath t = putPubKeyMap S.put t . fmap PSBTHDPath -newtype PSBTHDPath = PSBTHDPath { unPSBTHDPath :: (Fingerprint, [KeyIndex]) }+newtype PSBTHDPath =+    PSBTHDPath { unPSBTHDPath :: (Fingerprint, [KeyIndex]) }     deriving (Show, Eq, Generic)  instance NFData PSBTHDPath  instance Serialize PSBTHDPath where     get = do-        VarInt valueSize <- get+        VarInt valueSize <- deserialize         guard $ valueSize `mod` 4 == 0         let numIndices = (fromIntegral valueSize - 4) `div` 4         PSBTHDPath <$>-            isolate+            S.isolate                 (fromIntegral valueSize)-                ((,) <$> getWord32le <*> getKeyIndexList numIndices)+                ((,) <$> S.getWord32le <*> getKeyIndexList numIndices)       where-        getKeyIndexList n = replicateM n getWord32le-    put (PSBTHDPath (fp, kis)) = putVarInt (B.length bs) >> putByteString bs+        getKeyIndexList n = replicateM n S.getWord32le++    put (PSBTHDPath (fp, kis)) = do+        putVarInt (B.length bs)+        S.putByteString bs       where-        bs = runPut $ putWord32le fp >> mapM_ putWord32le kis+        bs = S.runPut $ S.putWord32le fp >> mapM_ S.putWord32le kis -putPubKeyMap :: (Serialize a, Enum t) => t -> HashMap PubKeyI a -> Put-putPubKeyMap t = void . HashMap.traverseWithKey putItem+putPubKeyMap :: Enum t => (a -> Put) -> t -> HashMap PubKeyI a -> Put+putPubKeyMap f t =+    void . HashMap.traverseWithKey putItem   where-    putItem k v = put (Key (enumWord8 t) (encode k)) >> put v+    putItem k v = do+        S.put $ Key (enumWord8 t) (runPutS (serialize k))+        f v  enumWord8 :: Enum a => a -> Word8 enumWord8 = fromIntegral . fromEnum
src/Haskoin/Transaction/Segwit.hs view
@@ -30,7 +30,9 @@     ) where  import           Data.ByteString            (ByteString)-import qualified Data.Serialize             as S+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Haskoin.Constants import           Haskoin.Keys.Common import           Haskoin.Script@@ -59,8 +61,8 @@ -- @since 0.11.0.0 toWitnessStack :: WitnessProgram -> WitnessStack toWitnessStack = \case-    P2WPKH (WitnessProgramPKH sig key) -> [encodeTxSig sig, S.encode key]-    P2WSH (WitnessProgramSH stack scr) -> stack <> [S.encode scr]+    P2WPKH (WitnessProgramPKH sig key) -> [encodeTxSig sig, runPutS (serialize key)]+    P2WSH (WitnessProgramSH stack scr) -> stack <> [runPutS (serialize scr)]     EmptyWitnessProgram                -> mempty  -- | High level representation of a P2WPKH witness@@ -89,10 +91,10 @@ viewWitnessProgram net so witness = case so of     PayWitnessPKHash _ | length witness == 2 -> do         sig    <- decodeTxSig net $ head witness-        pubkey <- S.decode $ witness !! 1+        pubkey <- runGetS deserialize $ witness !! 1         return . P2WPKH $ WitnessProgramPKH sig pubkey     PayWitnessScriptHash _ | not (null witness) -> do-        redeemScript <- S.decode $ last witness+        redeemScript <- runGetS deserialize $ last witness         return . P2WSH $ WitnessProgramSH (init witness) redeemScript     _ | null witness -> return EmptyWitnessProgram       | otherwise    -> Left "viewWitnessProgram: Invalid witness program"@@ -112,7 +114,7 @@             (PayPK _, [sigBS]) ->                 SpendPK <$> decodeTxSig net sigBS             (PayPKHash _, [sigBS, keyBS]) ->-                SpendPKHash <$> decodeTxSig net sigBS <*> S.decode keyBS+                SpendPKHash <$> decodeTxSig net sigBS <*> runGetS deserialize keyBS             (PayMulSig _ _, "" : sigsBS) ->                 SpendMulSig <$> traverse (decodeTxSig net) sigsBS             _ -> Left "decodeWitnessInput: Non-standard script output"@@ -138,7 +140,7 @@ simpleInputStack :: SimpleInput -> [ByteString] simpleInputStack = \case     SpendPK sig       -> [f sig]-    SpendPKHash sig k -> [f sig, S.encode k]+    SpendPKHash sig k -> [f sig, runPutS (serialize k)]     SpendMulSig sigs  -> "" : fmap f sigs   where     f TxSignatureEmpty = ""
src/Haskoin/Util.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP                   #-}+{-# LANGUAGE LambdaCase            #-} {-# LANGUAGE MultiParamTypeClasses #-} {-| Module      : Haskoin.Util@@ -17,7 +18,9 @@     , integerToBS     , hexBuilder     , encodeHex+    , encodeHexLazy     , decodeHex+    , decodeHexLazy     , getBits        -- * Maybe & Either Helpers@@ -40,23 +43,43 @@     , dropFieldLabel     , dropSumLabels +      -- * Serialization Helpers+    , putList, getList+    , putMaybe, getMaybe+    , putLengthBytes, getLengthBytes+    , putInteger, getInteger+    , putInt32be, getInt32be+    , putInt64be, getInt64be+    , getIntMap, putIntMap+    , getTwo, putTwo+     ) where -import           Control.Monad           (guard)-import           Control.Monad.Except    (ExceptT (..), liftEither)-import           Data.Aeson.Types        (Options (..), SumEncoding (..),-                                          defaultOptions, defaultTaggedObject)+import           Control.Monad+import           Control.Monad.Except        (ExceptT (..), liftEither)+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.ByteString             (ByteString)+import qualified Data.ByteString             as BS+import qualified Data.ByteString.Base16      as B16 import           Data.ByteString.Builder-import qualified Data.ByteString.Lazy    as BL-import           Data.Char               (toLower)+import qualified Data.ByteString.Lazy        as BL+import qualified Data.ByteString.Lazy.Base16 as BL16+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial+import           Data.Char                   (toLower)+import           Data.Int+import           Data.IntMap                 (IntMap)+import qualified Data.IntMap                 as IntMap import           Data.List-import           Data.Text               (Text)-import qualified Data.Text.Encoding      as E-import           Data.Word               (Word8)+import           Data.Text                   (Text)+import qualified Data.Text.Encoding          as E+import qualified Data.Text.Lazy              as TL+import qualified Data.Text.Lazy.Encoding     as EL+import           Data.Word  -- ByteString helpers @@ -76,23 +99,23 @@     f 0 = Nothing     f x = Just (fromInteger x :: Word8, x `shiftR` 8) -hexBuilder :: ByteString -> Builder-hexBuilder = byteStringHex+hexBuilder :: BL.ByteString -> Builder+hexBuilder = lazyByteStringHex --- | Encode as string of human-readable hex characters. encodeHex :: ByteString -> Text-encodeHex = E.decodeUtf8 . BL.toStrict . toLazyByteString . byteStringHex+encodeHex = B16.encodeBase16 --- | Decode string of human-readable hex characters.+-- | Encode as string of human-readable hex characters.+encodeHexLazy :: BL.ByteString -> TL.Text+encodeHexLazy = BL16.encodeBase16+ decodeHex :: Text -> Maybe ByteString-# if MIN_VERSION_base16_bytestring(1,0,0)-decodeHex = eitherToMaybe . B16.decode . E.encodeUtf8-# else-decodeHex text =-    let (x, b) = B16.decode (E.encodeUtf8 text)-    in guard (b == BS.empty) >> return x-# endif+decodeHex = eitherToMaybe . B16.decodeBase16 . E.encodeUtf8 +-- | Decode string of human-readable hex characters.+decodeHexLazy :: TL.Text -> Maybe BL.ByteString+decodeHexLazy = eitherToMaybe . BL16.decodeBase16 . EL.encodeUtf8+ -- | Obtain 'Int' bits from beginning of 'ByteString'. Resulting 'ByteString' -- will be smallest required to hold that many bits, padded with zeroes to the -- right.@@ -205,3 +228,125 @@                 out' = ((acc `shiftR` bits') .&. maxv) : out             in inner acc out' bits'         | otherwise = (out, bits)++--+-- Serialization helpers+--++putInt32be :: MonadPut m => Int32 -> m ()+putInt32be n+    | n < 0 = putWord32be (complement (fromIntegral (abs n)) + 1)+    | otherwise = putWord32be (fromIntegral (abs n))++getInt32be :: MonadGet m => m Int32+getInt32be = do+    n <- getWord32be+    if testBit n 31+        then return (negate (complement (fromIntegral n) + 1))+        else return (fromIntegral n)++putInt64be :: MonadPut m => Int64 -> m ()+putInt64be n+    | n < 0 = putWord64be (complement (fromIntegral (abs n)) + 1)+    | otherwise = putWord64be (fromIntegral (abs n))++getInt64be :: MonadGet m => m Int64+getInt64be = do+    n <- getWord64be+    if testBit n 63+        then return (negate (complement (fromIntegral n) + 1))+        else return (fromIntegral n)++putInteger :: MonadPut m => Integer -> m ()+putInteger n+    | n >= lo && n <= hi = do+          putWord8 0x00+          putInt32be (fromIntegral n)+    | otherwise = do+          putWord8 0x01+          putWord8 (fromIntegral (signum n))+          let len = (nrBits (abs n) + 7) `div` 8+          putWord64be (fromIntegral len)+          mapM_ putWord8 (unroll (abs n))+  where+    lo = fromIntegral (minBound :: Int32)+    hi = fromIntegral (maxBound :: Int32)++getInteger :: MonadGet m => m Integer+getInteger =+    getWord8 >>= \case+    0 -> fromIntegral <$> getInt32be+    _ -> do+        sign  <- getWord8+        bytes <- getList getWord8+        let v = roll bytes+        return $! if sign == 0x01 then v else - v++putMaybe :: MonadPut m => (a -> m ()) -> Maybe a -> m ()+putMaybe f Nothing  = putWord8 0x00+putMaybe f (Just x) = putWord8 0x01 >> f x++getMaybe :: MonadGet m => m a -> m (Maybe a)+getMaybe f =+    getWord8 >>= \case+    0x00 -> return Nothing+    0x01 -> Just <$> f+    _    -> fail "Not a Maybe"++putLengthBytes :: MonadPut m => ByteString -> m ()+putLengthBytes bs = do+    putWord64be (fromIntegral (BS.length bs))+    putByteString bs++getLengthBytes :: MonadGet m => m ByteString+getLengthBytes = do+    len <- fromIntegral <$> getWord64be+    getByteString len++--+-- Fold and unfold an Integer to and from a list of its bytes+--+unroll :: (Integral a, Bits a) => a -> [Word8]+unroll = unfoldr step+  where+    step 0 = Nothing+    step i = Just (fromIntegral i, i `shiftR` 8)++roll :: (Integral a, Bits a) => [Word8] -> a+roll   = foldr unstep 0+  where+    unstep b a = a `shiftL` 8 .|. fromIntegral b++nrBits :: (Ord a, Integral a) => a -> Int+nrBits k =+    let expMax = until (\e -> 2 ^ e > k) (* 2) 1+        findNr :: Int -> Int -> Int+        findNr lo hi+            | mid == lo = hi+            | 2 ^ mid <= k = findNr mid hi+            | 2 ^ mid > k  = findNr lo mid+         where mid = (lo + hi) `div` 2+    in findNr (expMax `div` 2) expMax++-- | Read as a list of pairs of int and element.+getIntMap :: MonadGet m => m Int -> m a -> m (IntMap a)+getIntMap i m = IntMap.fromList <$> getList (getTwo i m)++putIntMap :: MonadPut m => (Int -> m ()) -> (a -> m ()) -> IntMap a -> m ()+putIntMap f g = putList (putTwo f g) . IntMap.toAscList++putTwo :: MonadPut m => (a -> m ()) -> (b -> m ()) -> (a, b) -> m ()+putTwo f g (x, y) = f x >> g y++getTwo :: MonadGet m => m a -> m b -> m (a, b)+getTwo f g = (,) <$> f <*> g++putList :: MonadPut m => (a -> m ()) -> [a] -> m ()+putList f ls = do+    putWord64be (fromIntegral (length ls))+    mapM_ f ls++getList :: MonadGet m => m a -> m [a]+getList f = do+    l <- fromIntegral <$> getWord64be+    replicateM l f
src/Haskoin/Util/Arbitrary/Script.hs view
@@ -274,7 +274,7 @@  arbitraryWitOutput :: Gen ScriptOutput arbitraryWitOutput = do-    ver <- choose (0, 16)+    ver <- choose (1, 16)     len <- choose (2, 40)     ws <- vectorOf len arbitrary     let bs = B.pack ws
src/Haskoin/Util/Arbitrary/Util.hs view
@@ -32,23 +32,24 @@ ) where -import           Control.Monad           (forM_, (<=<))-import qualified Data.Aeson              as A-import qualified Data.Aeson.Encoding     as A-import qualified Data.Aeson.Types        as A-import           Data.ByteString         (ByteString, pack)-import qualified Data.ByteString.Short   as BSS-import qualified Data.Map.Strict         as Map+import           Control.Monad         (forM_, (<=<))+import qualified Data.Aeson            as A+import qualified Data.Aeson.Encoding   as A+import qualified Data.Aeson.Types      as A+import           Data.ByteString       (ByteString, pack)+import qualified Data.ByteString.Short as BSS+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial+import qualified Data.Map.Strict       as Map import           Data.Proxy-import qualified Data.Serialize          as S-import           Data.Time.Clock         (UTCTime (..))-import           Data.Time.Clock.POSIX   (posixSecondsToUTCTime)-import qualified Data.Typeable           as T-import           Data.Word               (Word32)+import           Data.Time.Clock       (UTCTime (..))+import           Data.Time.Clock.POSIX (posixSecondsToUTCTime)+import qualified Data.Typeable         as T+import           Data.Word             (Word32) import           Haskoin.Constants-import           Test.Hspec              (Spec, describe, shouldBe,-                                          shouldSatisfy)-import           Test.Hspec.QuickCheck   (prop)+import           Test.Hspec            (Spec, describe, shouldBe, shouldSatisfy)+import           Test.Hspec.QuickCheck (prop) import           Test.QuickCheck  -- | Arbitrary strict 'ByteString'.@@ -94,7 +95,7 @@ -- Helpers for creating Serial and JSON Identity tests  data SerialBox =-    forall a. (Show a, Eq a, T.Typeable a, S.Serialize a) =>+    forall a. (Show a, Eq a, T.Typeable a, Serial a) =>               SerialBox (Gen a)  data ReadBox =@@ -115,7 +116,7 @@  testIdentity :: [SerialBox] -> [ReadBox] -> [JsonBox] -> [NetBox] -> Spec testIdentity serialVals readVals jsonVals netVals = do-    describe "Data.Serialize Encoding" $+    describe "Binary Encoding" $         forM_ serialVals $ \(SerialBox g) -> testSerial g     describe "Read/Show Encoding" $         forM_ readVals $ \(ReadBox g) -> testRead g@@ -124,12 +125,13 @@     describe "Data.Aeson Encoding with Network" $         forM_ netVals $ \(NetBox (j,e,p,g)) -> testNetJson j e p g --- | Generate Data.Serialize identity tests+-- | Generate binary identity tests testSerial ::-       (Eq a, Show a, T.Typeable a, S.Serialize a) => Gen a -> Spec+       (Eq a, Show a, T.Typeable a, Serial a) => Gen a -> Spec testSerial gen =-    prop ("Data.Serialize encoding/decoding identity for " <> name) $-    forAll gen $ \x -> (S.decode . S.encode) x `shouldBe` Right x+    prop ("Binary encoding/decoding identity for " <> name) $+    forAll gen $ \x ->+    (runGetS deserialize . runPutS . serialize) x `shouldBe` Right x   where     name = show $ T.typeRep $ proxy gen     proxy :: Gen a -> Proxy a
test/Haskoin/Crypto/HashSpec.hs view
@@ -7,8 +7,10 @@ import qualified Data.ByteString.Char8   as C import qualified Data.ByteString.Lazy    as BL import qualified Data.ByteString.Short   as BSS+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Maybe              (fromJust)-import           Data.Serialize          as S import           Data.String             (fromString) import           Data.String.Conversions import           Data.Text               (Text)@@ -17,15 +19,14 @@ import           Haskoin.Crypto import           Haskoin.Util import           Haskoin.Util.Arbitrary+import           Test.HUnit import           Test.Hspec import           Test.Hspec.QuickCheck-import           Test.HUnit import           Test.QuickCheck  serialVals :: [SerialBox] serialVals =     [ SerialBox arbitraryBS-    , SerialBox arbitraryBSS     , SerialBox arbitraryHash160     , SerialBox arbitraryHash256     , SerialBox arbitraryHash512@@ -50,13 +51,13 @@             prop "decodeCompact . encodeCompact i == i" decEncCompact             prop "from string Hash512" $                 forAll arbitraryHash512 $ \h ->-                    fromString (cs $ encodeHex $ encode h) == h+                    fromString (cs $ encodeHex $ runPutS $ serialize h) == h             prop "from string Hash256" $                 forAll arbitraryHash256 $ \h ->-                    fromString (cs $ encodeHex $ encode h) == h+                    fromString (cs $ encodeHex $ runPutS $ serialize h) == h             prop "from string Hash160" $                 forAll arbitraryHash160 $ \h ->-                    fromString (cs $ encodeHex $ encode h) == h+                    fromString (cs $ encodeHex $ runPutS $ serialize h) == h         describe "Test Vectors" $ do             it "Passes RIPEMD160 test vectors" $                 mapM_ (testVector ripemd160 getHash160) ripemd160Vectors
test/Haskoin/Keys/ExtendedSpec.hs view
@@ -6,9 +6,11 @@ import           Data.Aeson                 as A import           Data.Bits                  ((.&.)) import qualified Data.ByteString.Lazy.Char8 as B8+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Either                (isLeft) import           Data.Maybe                 (fromJust, isJust, isNothing)-import           Data.Serialize             as S import           Data.String                (fromString) import           Data.String.Conversions    (cs) import           Data.Text                  (Text)@@ -19,9 +21,9 @@ import           Haskoin.Util import           Haskoin.Util.Arbitrary import           Haskoin.UtilSpec           (customCerealID)+import           Test.HUnit                 (Assertion, assertBool, assertEqual) import           Test.Hspec import           Test.Hspec.QuickCheck-import           Test.HUnit                 (Assertion, assertBool, assertEqual) import           Test.QuickCheck            hiding ((.&.))  serialVals :: [SerialBox]@@ -309,8 +311,8 @@  runVector :: XPrvKey -> TestVector -> Assertion runVector m v = do-    assertBool "xPrvID" $ encodeHex (S.encode $ xPrvID m) == v !! 0-    assertBool "xPrvFP" $ encodeHex (S.encode $ xPrvFP m) == v !! 1+    assertBool "xPrvID" $ encodeHex (runPutS . serialize $ xPrvID m) == v !! 0+    assertBool "xPrvFP" $ encodeHex (runPutS . serialize $ xPrvFP m) == v !! 1     assertBool "xPrvAddr" $         addrToText btc (xPubAddr $ deriveXPubKey m) == Just (v !! 2)     assertBool "bip44Addr" $@@ -320,18 +322,18 @@     assertBool "xPrvWIF" $ xPrvWif btc m == v !! 5     assertBool "pubKey" $         encodeHex (exportPubKey True $ xPubKey $ deriveXPubKey m) == v !! 6-    assertBool "chain code" $ encodeHex (S.encode $ xPrvChain m) == v !! 7+    assertBool "chain code" $ encodeHex (runPutS . serialize $ xPrvChain m) == v !! 7     assertBool "Hex PubKey" $-        encodeHex (runPut $ putXPubKey btc $ deriveXPubKey m) == v !! 8-    assertBool "Hex PrvKey" $ encodeHex (runPut (putXPrvKey btc m)) == v !! 9+        encodeHex (runPutS $ putXPubKey btc $ deriveXPubKey m) == v !! 8+    assertBool "Hex PrvKey" $ encodeHex (runPutS (putXPrvKey btc m)) == v !! 9     assertBool "Base58 PubKey" $ xPubExport btc (deriveXPubKey m) == v !! 10     assertBool "Base58 PrvKey" $ xPrvExport btc m == v !! 11  -- This function was used to generate addition data for the test vectors genVector :: XPrvKey -> [(Text, Text)] genVector m =-    [ ("xPrvID", encodeHex (S.encode $ xPrvID m))-    , ("xPrvFP", encodeHex (S.encode $ xPrvFP m))+    [ ("xPrvID", encodeHex (runPutS . serialize $ xPrvID m))+    , ("xPrvFP", encodeHex (runPutS . serialize $ xPrvFP m))     , ("xPrvAddr", fromJust $ addrToText btc (xPubAddr $ deriveXPubKey m))     , ( "bip44Addr"       , fromJust $@@ -339,9 +341,9 @@     , ("prvKey", encodeHex (getSecKey $ xPrvKey m))     , ("xPrvWIF", xPrvWif btc m)     , ("pubKey", encodeHex (exportPubKey True $ xPubKey $ deriveXPubKey m))-    , ("chain code", encodeHex (S.encode $ xPrvChain m))-    , ("Hex PubKey", encodeHex (runPut $ putXPubKey btc $ deriveXPubKey m))-    , ("Hex PrvKey", encodeHex (runPut (putXPrvKey btc m)))+    , ("chain code", encodeHex (runPutS . serialize $ xPrvChain m))+    , ("Hex PubKey", encodeHex (runPutS $ putXPubKey btc $ deriveXPubKey m))+    , ("Hex PrvKey", encodeHex (runPutS (putXPrvKey btc m)))     ]  parseVector :: TestKey -> [TestVector] -> [(Text, XPrvKey, TestVector)]
test/Haskoin/KeysSpec.hs view
@@ -7,8 +7,11 @@ import           Data.Aeson.Lens import qualified Data.ByteString         as BS import qualified Data.ByteString.Char8   as C+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Maybe-import           Data.Serialize          as S+import qualified Data.Serialize          as S import           Data.String             (fromString) import           Data.String.Conversions (cs) import           Data.Text               (Text)@@ -20,15 +23,14 @@ import           Haskoin.Util import           Haskoin.Util.Arbitrary import           Haskoin.UtilSpec        (readTestFile)+import           Test.HUnit import           Test.Hspec import           Test.Hspec.QuickCheck-import           Test.HUnit import           Test.QuickCheck  serialVals :: [SerialBox] serialVals =-    [ SerialBox (arbitrary :: Gen SecKey)-    , SerialBox (snd <$> arbitraryKeyPair) -- PubKeyI+    [ SerialBox (snd <$> arbitraryKeyPair) -- PubKeyI     ]  readVals :: [ReadBox]@@ -51,7 +53,7 @@             forAll arbitraryKeyPair (isCanonicalPubKey . snd)         prop "Public key fromString identity" $             forAll arbitraryKeyPair $ \(_, k) ->-                fromString (cs . encodeHex $ S.encode k) == k+                fromString (cs . encodeHex $ runPutS $ serialize k) == k     describe "SecKey properties" $         prop "fromWif . toWif identity" $         forAll arbitraryNetwork $ \net ->@@ -88,13 +90,13 @@     -- Non-canonical public key: compressed nor uncompressed     (BS.index bs 0 `notElem` [2,3,4])   where-    bs = S.encode p+    bs = runPutS $ serialize p  testMiniKey :: Assertion testMiniKey =     assertEqual "fromMiniKey" (Just res) (go "S6c56bnXQiBjk9mqSYE7ykVQ7NzrRy")   where-    go = fmap (encodeHex . S.encode . secKeyData) . fromMiniKey+    go = fmap (encodeHex . runPutS . S.put . secKeyData) . fromMiniKey     res = "4c7a9640c72dc2099f23715d0c8a0d8a35f8906e3cab61dd3f78b67bf887c9ab"  -- Test vectors from:@@ -107,14 +109,14 @@         -- Test from WIF to SecKey         let isComp = obj ^?! key "isCompressed" . _Bool             prvKeyM = fromWif net a-            prvKeyHexM = encodeHex . S.encode . secKeyData <$> prvKeyM+            prvKeyHexM = encodeHex . runPutS . S.put . secKeyData <$> prvKeyM         assertBool "Valid PrvKey" $ isJust prvKeyM         assertEqual "Valid compression" (Just isComp) (secKeyCompressed <$> prvKeyM)         assertEqual "WIF matches payload" (Just payload) prvKeyHexM         let prvAsPubM = (eitherToMaybe . decodeOutputBS <=< decodeHex) a         assertBool "PrvKey is invalid ScriptOutput" $ isNothing prvAsPubM         -- Test from SecKey to WIF-        let secM = eitherToMaybe . S.decode =<< decodeHex payload+        let secM = eitherToMaybe . runGetS S.get =<< decodeHex payload             wifM = toWif net . wrapSecKey isComp <$> secM         assertEqual "Payload matches WIF" (Just a) wifM     | otherwise = do@@ -124,7 +126,9 @@         assertBool ("Valid Address " <> cs a) $ isJust addrM         assertEqual "Address matches payload" (Just payload) scriptM         let pubAsWifM = fromWif net a-            pubAsSecM = eitherToMaybe . S.decode =<< decodeHex a :: Maybe SecKey+            pubAsSecM =+                eitherToMaybe . runGetS S.get =<<+                decodeHex a :: Maybe SecKey         assertBool "Address is invalid Wif" $ isNothing pubAsWifM         assertBool "Address is invalid PrvKey" $ isNothing pubAsSecM         -- Test Script to Addr@@ -145,7 +149,7 @@ testKeyIOInvalidVector :: [Text] -> Assertion testKeyIOInvalidVector [a] = do     let wifMs = (`fromWif` a) <$> allNets-        secKeyM = (eitherToMaybe . S.decode <=< decodeHex) a :: Maybe SecKey+        secKeyM = (eitherToMaybe . runGetS S.get <=< decodeHex) a :: Maybe SecKey         scriptM = (eitherToMaybe . decodeOutputBS <=< decodeHex) a :: Maybe ScriptOutput     assertBool "Payload is invalid WIF" $ all isNothing wifMs     assertBool "Payload is invalid SecKey" $ isNothing secKeyM
test/Haskoin/NetworkSpec.hs view
@@ -1,8 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} module Haskoin.NetworkSpec (spec) where +import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Maybe             (fromJust)-import           Data.Serialize         as S import           Data.Text              (Text) import           Data.Word              (Word32) import           Haskoin.Address@@ -13,9 +15,9 @@ import           Haskoin.Util import           Haskoin.Util.Arbitrary import           Haskoin.UtilSpec       (customCerealID)+import           Test.HUnit             (Assertion, assertBool, assertEqual) import           Test.Hspec import           Test.Hspec.QuickCheck-import           Test.HUnit             (Assertion, assertBool, assertEqual) import           Test.QuickCheck  serialVals :: [SerialBox]@@ -67,7 +69,7 @@     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+        runPutS (serialize f4) == bs   where     f0 = bloomCreate 3 0.01 n BloomUpdateAll     f1 = bloomInsert f0 v1@@ -88,11 +90,11 @@ bloomFilter3 :: Assertion bloomFilter3 =     assertBool "Bloom filter serialization is incorrect" $-        S.encode f2 == bs+        runPutS (serialize f2) == bs   where     f0 = bloomCreate 2 0.001 0 BloomUpdateAll-    f1 = bloomInsert f0 $ S.encode p-    f2 = bloomInsert f1 $ S.encode $ getAddrHash160 $ pubKeyAddr p+    f1 = bloomInsert f0 $ runPutS $ serialize p+    f2 = bloomInsert f1 $ runPutS $ serialize $ getAddrHash160 $ pubKeyAddr p     k = fromJust $ fromWif btc "5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C"     p = derivePubKeyI k     bs = fromJust $ decodeHex "038fc16b080000000000000001"@@ -105,7 +107,7 @@         relevantOutputHash = fromJust $ decodeHex"03f47604ea2736334151081e13265b4fe38e6fa8"         bf1 = bloomInsert bf0 relevantOutputHash         bf2 = fromJust $ bloomRelevantUpdate bf1 relevantTx-        spendTxInput = encode .prevOutput <$> txIn spendRelevantTx+        spendTxInput = runPutS . serialize . prevOutput <$> txIn spendRelevantTx  irrelevantOutputNotUpdated :: Assertion irrelevantOutputNotUpdated = assertEqual "Bloom filter not updated" Nothing bf2
test/Haskoin/ScriptSpec.hs view
@@ -5,10 +5,12 @@ import           Data.Aeson              as A import           Data.ByteString         (ByteString) import qualified Data.ByteString         as B+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Either import           Data.List import           Data.Maybe-import           Data.Serialize          as S import           Data.String import           Data.String.Conversions (cs) import           Data.Text               (Text)@@ -21,9 +23,9 @@ import           Haskoin.Util import           Haskoin.Util.Arbitrary import           Haskoin.UtilSpec        (readTestFile)+import           Test.HUnit              as HUnit import           Test.Hspec import           Test.Hspec.QuickCheck-import           Test.HUnit              as HUnit import           Test.QuickCheck import           Text.Read @@ -89,21 +91,26 @@             decodeInput net (encodeInput si) `shouldBe` Right si     prop "can sort multisig scripts" $         forAll arbitraryMSOutput $ \out ->-            map S.encode (getOutputMulSigKeys (sortMulSig out)) `shouldSatisfy` \xs ->-                xs == sort xs+            map+            (runPutS . serialize)+            (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 $ B.replicate 32 1-        decodeInput net (Script [OP_0, opPushData $ S.encode pk]) `shouldBe`+        let pk = derivePubKeyI $+                 wrapSecKey True $ fromJust $ secKey $ B.replicate 32 1+        decodeInput net (Script [OP_0, opPushData $ runPutS $ serialize pk])+            `shouldBe`             Right (RegularInput (SpendPKHash TxSignatureEmpty pk))-        decodeInput net (Script [OP_0, OP_0]) `shouldBe`+        decodeInput net (Script [OP_0, OP_0])+            `shouldBe`             Right (RegularInput (SpendMulSig [TxSignatureEmpty]))-        decodeInput net (Script [OP_0, OP_0, OP_0, OP_0]) `shouldBe`+        decodeInput net (Script [OP_0, OP_0, OP_0, OP_0])+            `shouldBe`             Right (RegularInput (SpendMulSig $ replicate 3 TxSignatureEmpty))  scriptSpec :: Network -> Spec@@ -189,7 +196,7 @@     txI =         TxIn         { prevOutput = nullOutPoint-        , scriptInput = S.encode $ Script [OP_0, OP_0]+        , scriptInput = runPutS $ serialize $ Script [OP_0, OP_0]         , txInSequence = maxBound         } @@ -216,7 +223,7 @@  replaceToken :: String -> String replaceToken str = case readMaybe $ "OP_" <> str of-    Just opcode -> "0x" <> cs (encodeHex $ S.encode (opcode :: ScriptOp))+    Just opcode -> "0x" <> cs (encodeHex $ runPutS $ serialize (opcode :: ScriptOp))     _           -> str  strictSigSpec :: Network -> Spec@@ -251,10 +258,10 @@             let tx = fromString txStr                 s =                     fromMaybe (error $ "Could not decode script: " <> cs scpStr) $-                    eitherToMaybe . S.decode =<< decodeHex (cs scpStr)+                    eitherToMaybe . runGetS deserialize =<< decodeHex (cs scpStr)                 sh = fromIntegral shI                 res =-                    eitherToMaybe . S.decode . B.reverse =<<+                    eitherToMaybe . runGetS deserialize . B.reverse =<<                     decodeHex (cs resStr)             Just (txSigHash net tx s 0 i sh) `shouldBe` res @@ -275,9 +282,9 @@             let tx = fromString txStr                 s =                     fromMaybe (error $ "Could not decode script: " <> cs scpStr) $-                    eitherToMaybe . S.decode =<< decodeHex (cs scpStr)+                    eitherToMaybe . runGetS deserialize =<< decodeHex (cs scpStr)                 sh = fromIntegral shI-                res = eitherToMaybe . S.decode =<< decodeHex (cs resStr)+                res = eitherToMaybe . runGetS deserialize =<< decodeHex (cs resStr)             Just (txSigHashForkId net tx s val i sh) `shouldBe` res  sigHashSpec :: Network -> Spec@@ -359,7 +366,7 @@   where     s = do         s' <- decodeHex ops-        eitherToMaybe $ S.decode s'+        eitherToMaybe $ runGetS deserialize s'     b = do         o <- s         d <- eitherToMaybe $ decodeOutput o@@ -413,7 +420,7 @@  encodeScriptVector :: Assertion encodeScriptVector =-    assertEqual "Encode script" res (encodeHex $ S.encode s)+    assertEqual "Encode script" res (encodeHex $ runPutS $ serialize s)   where     res =         "514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58b\
test/Haskoin/Transaction/PartialSpec.hs view
@@ -4,14 +4,17 @@  import           Control.Monad.Fail          (MonadFail) import           Data.ByteString             (ByteString)+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Either                 (fromRight, isLeft, isRight) import           Data.HashMap.Strict         (fromList, singleton) import           Data.Maybe                  (fromJust, isJust) import           Data.Serialize              as S import           Data.Text                   (Text)-import           Test.Hspec import           Test.HUnit                  (Assertion, assertBool,                                               assertEqual)+import           Test.Hspec import           Test.QuickCheck  import           Haskoin.Address@@ -150,10 +153,11 @@  hexScript :: Text -> ByteString hexScript =-    either (error "Could not decode script") encodeScript . S.decode . fromJust . decodeHex+    either (error "Could not decode script") encodeScript .+    runGetS deserialize . fromJust . decodeHex   where     encodeScript :: Script -> ByteString-    encodeScript = S.encode+    encodeScript = runPutS . serialize  invalidVecTest :: Text -> Assertion invalidVecTest = assertBool "invalid psbt" . isLeft . decodeHexPSBT@@ -194,7 +198,12 @@     currTx = unfinalizedTx (txHash prevTx)     prevTx = testUtxo [prevOut]     prevOutScript = addressToScript (pubKeyAddr pubKey)-    prevOut = TxOut { outValue = 200000000, scriptOutput = S.encode prevOutScript }+    prevOut =+        TxOut+        {+            outValue = 200000000,+            scriptOutput = runPutS (serialize prevOutScript)+        }     h = txSigHash net currTx prevOutScript (outValue prevOut) 0 sigHashAll     sig = encodeTxSig $ TxSignature (signHash (secKeyData prvKey) h) sigHashAll 
test/Haskoin/TransactionSpec.hs view
@@ -2,14 +2,16 @@  module Haskoin.TransactionSpec (spec) where -import qualified Data.ByteString            as B+import qualified Data.ByteString         as B+import           Data.Bytes.Get+import           Data.Bytes.Put+import           Data.Bytes.Serial import           Data.Either import           Data.Maybe-import           Data.Serialize             as S-import           Data.String                (fromString)+import           Data.String             (fromString) import           Data.String.Conversions-import           Data.Text                  (Text)-import           Data.Word                  (Word32, Word64)+import           Data.Text               (Text)+import           Data.Word               (Word32, Word64) import           Haskoin.Address import           Haskoin.Constants import           Haskoin.Keys@@ -17,9 +19,9 @@ import           Haskoin.Transaction import           Haskoin.Util import           Haskoin.Util.Arbitrary+import           Test.HUnit import           Test.Hspec import           Test.Hspec.QuickCheck-import           Test.HUnit import           Test.QuickCheck  serialVals :: [SerialBox]@@ -94,7 +96,7 @@ testTxidVector (tid, tx) =     assertEqual "txid" (Just tid) (txHashToHex . txHash <$> txM)   where-    txM = eitherToMaybe . S.decode =<< decodeHex tx+    txM = eitherToMaybe . runGetS deserialize =<< decodeHex tx  txidVectors :: [(Text, Text)] txidVectors =@@ -156,7 +158,10 @@  testPKHashVector :: ([(Text, Word32)], [(Text, Word64)], Text) -> Assertion testPKHashVector (is, os, res) =-    assertEqual "Build PKHash Tx" (Right res) (encodeHex . S.encode <$> txE)+    assertEqual+    "Build PKHash Tx"+    (Right res)+    (encodeHex . runPutS . serialize <$> txE)   where     txE = buildAddrTx btc (map f is) os     f (tid, ix) = OutPoint (fromJust $ hexToTxHash tid) ix@@ -223,7 +228,7 @@   where     delta = pki + sum (map fst msi)     guess = guessTxSize pki msi pkout msout-    len = B.length $ S.encode tx+    len = B.length $ runPutS $ serialize tx     ins = map f $ txIn tx     f i =         fromRight (error "Could not decode input") $@@ -231,7 +236,7 @@     pki = length $ filter isSpendPKHash ins     msi = concatMap shData ins     shData (ScriptHashInput _ (PayMulSig keys r)) = [(r, length keys)]-    shData _ = []+    shData _                                      = []     out =         map             (fromRight (error "Could not decode transaction output") .