multihash-serialise (empty) → 0.1.0.0
raw patch · 6 files changed
+209/−0 lines, 6 filesdep +basedep +bytestringdep +cryptonite
Dependencies added: base, bytestring, cryptonite, hedgehog, memory, multibase, multihash-cryptonite, multihash-serialise, serialise
Files
- CHANGELOG.md +0/−0
- LICENSE +30/−0
- README.md +1/−0
- multihash-serialise.cabal +77/−0
- src/Codec/Serialise/Multihash.hs +61/−0
- test/properties/Main.hs +40/−0
+ CHANGELOG.md view
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2018, Monadic GmbH++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Monadic GmbH nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,1 @@+CBOR encoding of [multihashes](../multihash-cryptonite), via [serialise](https://hackage.haskell.org/package/serialise).
+ multihash-serialise.cabal view
@@ -0,0 +1,77 @@+cabal-version: 2.2+build-type: Simple++name: multihash-serialise+version: 0.1.0.0+synopsis: CBOR encoding of multihashes+homepage: https://github.com/oscoin/ipfs+bug-reports: https://github.com/oscoin/ipfs/issues+license: BSD-3-Clause+license-file: LICENSE+author: Kim Altintop+maintainer: Kim Altintop <kim@monadic.xyz>, Monadic Team <team@monadic.xyz>+copyright: 2018 Monadic GmbH++category: Codec++extra-source-files:+ CHANGELOG.md+ , README.md++source-repository head+ type: git+ location: https://github.com/oscoin/ipfs++common common+ default-language: Haskell2010+ ghc-options:+ -Wall+ -Wcompat+ -Wincomplete-uni-patterns+ -Wincomplete-record-updates+ -Wredundant-constraints+ -fprint-expanded-synonyms+ -funbox-small-strict-fields++library+ import: common+ hs-source-dirs: src+ exposed-modules:+ Codec.Serialise.Multihash++ build-depends:+ base >= 4.9 && < 5+ , bytestring+ , cryptonite > 0.13+ , memory >= 0.11+ , multibase+ , multihash-cryptonite+ , serialise++ ghc-options:+ -Wall+ -Wcompat+ -Wincomplete-uni-patterns+ -Wincomplete-record-updates+ -Wredundant-constraints+ -fprint-expanded-synonyms+ -funbox-small-strict-fields++test-suite properties+ import: common+ main-is: Main.hs+ hs-source-dirs: test/properties+ type: exitcode-stdio-1.0++ build-depends:+ base+ , cryptonite+ , hedgehog+ , multihash-serialise+ , serialise++ ghc-options:+ -threaded+ -rtsopts+ -with-rtsopts=-N+
+ src/Codec/Serialise/Multihash.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- |+-- Copyright : 2018 Monadic GmbH+-- License : BSD3+-- Maintainer : kim@monadic.xyz, team@monadic.xyz+-- Stability : provisional+-- Portability : non-portable (GHC extensions)+--+-- A mapping of <https://github.com/multiformats/multihash multihash> to CBOR.+--+-- Instead of an opaque, multihash-encoded blob, this provides a tagged CBOR+-- encoding where the hash algorithm used is a 'Word16' field containing the+-- multihash code for the algorithm, followed by the digest bytes.+module Codec.Serialise.Multihash+ ( encode+ , decode++ -- * Re-exports+ , Multihashable+ )+where++import qualified Codec.Serialise as CBOR+import qualified Codec.Serialise.Decoding as CBOR+import qualified Codec.Serialise.Encoding as CBOR+import Control.Applicative (liftA2)+import qualified Crypto.Hash as C+import Data.ByteArray (convert)+import Data.Multihash (Multihashable)+import qualified Data.Multihash as Multi+import Data.Proxy (Proxy(..))++-- | Multihash-like CBOR 'CBOR.Encoding' of a 'C.Digest'.+encode :: Multihashable a => C.Digest a -> CBOR.Encoding+encode dig =+ CBOR.encodeListLen 3+ <> CBOR.encodeWord 0 -- constructor tag / version+ <> CBOR.encode (Multi.toCode (Multi.fromCryptonite dig))+ <> CBOR.encodeBytes (convert dig)++-- | CBOR 'CBOR.Decoder' to decode a 'C.Digest' encoded via 'encodeCBOR'.+decode :: forall s a. Multihashable a => CBOR.Decoder s (C.Digest a)+decode = do+ pre <- liftA2 (,) CBOR.decodeListLen CBOR.decodeWord+ case pre of+ (3, 0) -> do+ rithm <- Multi.fromCode <$> CBOR.decode+ case rithm of+ Nothing -> fail "Unknown HashAlgorithm"+ Just a+ | Multi.fromCryptonite (Proxy @a) /= a ->+ fail "Algorithm Mismatch"+ | otherwise -> do+ bytes <- CBOR.decodeBytes+ maybe (fail "Invalid Digest") pure+ $ C.digestFromByteString bytes++ _ -> fail "Multihash: Invalid Tag"
+ test/properties/Main.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE TemplateHaskell #-}++module Main (main) where++import Control.Monad (unless)+import qualified Crypto.Hash as C+import System.Exit (exitFailure)+import System.IO (BufferMode(..), hSetBuffering, stderr, stdout)++import qualified Codec.Serialise as CBOR+import Codec.Serialise.Multihash (Multihashable)+import qualified Codec.Serialise.Multihash as Multihash++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++main :: IO ()+main = do+ hSetBuffering stdout LineBuffering+ hSetBuffering stderr LineBuffering++ ok <- props+ unless ok exitFailure++props :: IO Bool+props = checkParallel $$(discover)++newtype Digest' a = Digest' { unDigest' :: C.Digest a }+ deriving (Eq, Show)++instance Multihashable a => CBOR.Serialise (Digest' a) where+ encode = Multihash.encode . unDigest'+ decode = Digest' <$> Multihash.decode++prop_roundtrip :: Property+prop_roundtrip = property $ do+ bs <- forAll $ Gen.bytes (Range.singleton 128)+ let digest = Digest' $ C.hashWith C.Blake2b_256 bs+ tripping digest CBOR.serialise CBOR.deserialiseOrFail