mfmts 

This project implements the specifications described by Protocol Lab's
multiformats written in Haskell.
cid - Content identitiers for hashed data
Provides functionality for the multiformats CID binary format. These modules
provide parsing CIDs from multibase prefixed digit strings, extracting CID data
from byte strings and serializing CIDs stored in memory into its binary format.
CID GitHub README example in GHCI:
λ> {-# LANGUAGE OverloadedStrings #-}
λ> import MultiFormats.CID (CID)
λ> import MultiFormats.CID.Parser qualified as CID
λ> import MultiFormats.CID.Errors qualified as CID
λ> CID.parser "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA" :: CID.Okay CID
Right CIDv1 {
DataCodec=MultiCodec(0x55, "raw"),
HashCodec=MultiHash(0x12, "sha2-256"),
HashDigest=[base58btc]("8S6sXBSX8wVLcT88GnuZpbvmaxetTmPri26tufEByBKS"),
HashSize=32
}
multibase - Multibase prefix data transcoding
Implements encoders and decoders for numeric basesytems identitified by a
specified prefix symbol. It implements transcoders from the basesystems library, allowing for different types of
bytestring data to be specified as type parameters.
Multibase GitHub README example in GHCI:
λ> {-# LANGUAGE OverloadedStrings #-}
λ> import MultiFormats.MultiBase.DigitTranscoder (decodeFromPrefix)
λ> import Data.ByteString.Short (ShortByteString)
λ> type Str = ShortByteString
λ> -- uppercase hexadecimal
λ> decodeFromPrefix "F4D756C74696261736520697320617765736F6D6521205C6F2F" :: Maybe Str
Just "Multibase is awesome! \\o/"
λ> -- base32 no padding
λ> decodeFromPrefix "BJV2WY5DJMJQXGZJANFZSAYLXMVZW63LFEEQFY3ZP" :: Maybe Str
Just "Multibase is awesome! \\o/"
λ> -- bitcoin base58
λ> decodeFromPrefix "zYAjKoNbau5KiqmHPmSxYCvn66dA1vLmwbt" :: Maybe Str
Just "Multibase is awesome! \\o/"
λ> -- base64 with padding
λ> decodeFromPrefix "MTXVsdGliYXNlIGlzIGF3ZXNvbWUhIFxvLw==" :: Maybe Str
Just "Multibase is awesome! \\o/"
multicodec - Magic number specifications
Provides lookup table and query functions for codecs defined from multiformats
multicodec. These are magic numbers that represent certain data encoded within
CIDs, mulithash and other related projects. This module has code which
is generated by a python script in the ipfshs
repo, and is automatically generated from CSV.
Example of looking up codecs:
λ> import MultiFormats.MultiCodec qualified as MC
λ> -- Resolving from codec values:
λ> MC.resolveCodecName $ MC.MultiCodec 0x1
Just "cidv1"
λ> -- Resolving from names:
λ> MC.resolveCodecValue "cidv1"
Just MultiCodec(0x1, "cidv1")
λ> MC.resolveCodecValue "cidv0"
Nothing
multihash - Multicodec hash function identifiers
Multihashes are a type of multicodec for identifying hash functions. This
code provides a lookup table for hash functions from the multicodec module, and
a way to get hash digests from specific functions over bytestrings, and to
verify multicodec values as valid multihash codecs.
Example of looking up hash functions and applying them:
λ> import MultiFormats.MultiCodec qualified as MC
λ> import MultiFormats.MultiHash qualified as MH
λ> -- Here's an example of how we can verify names and codec values as valid
λ> -- hash functions.
λ> MH.resolveHashCodec $ MC.MultiCodec 0x12
Just MultiHash(0x12, "sha2-256")
λ> MH.resolveHashName "sha2-256"
Just MultiHash(0x12, "sha2-256")
λ> -- Building a function call that hashes the string "Hello World!" using the
λ> -- sha2-256 algorithm, then outputs the digest as hexadecimal:
λ> import Data.BaseSystem.Lazy (encoder)
λ> import Data.BaseSystem.DigitSystem (base16lower)
λ> import Data.ByteString.Builder qualified as Builder
λ> import Data.Maybe (fromJust)
λ> let sha256 = MH.multiHashFunction $ fromJust (MH.resolveHashName "sha2-256")
λ> let input = Builder.string8 "Hello World!"
λ> encoder base16lower $ sha256 input
"7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069"
varint - Unsigned variable length integers
Provides parsing and serialization for multiformats unsigned binary varints,
with the special caveat from multiformats that requires them always to be
minimally encoded, so this project also verifies that the varint inputs comply
with the rules of the multiformats specifiation.
Varint GitHub README example in GHCI using packValue from the basesystems library to transfer constants into
bytestrings. We can then use extractVarInt to get the varint representation
from the bytes:
λ> import Data.BaseSystem.BinaryTranscoder (packValue)
λ> import Data.ByteString.Short (ShortByteString)
λ> import MultiFormats.VarInt (VarInt, extractVarInt)
λ> import MultiFormats.VarInt.Errors qualified as VarInt
λ> -- Make alias so we don't get type warnings
λ> let packInteger x = packValue (x :: Integer)
λ> -- 7-bit values fit into 1 byte:
λ> extractVarInt (packInteger 0x01) :: VarInt.Okay (VarInt, ShortByteString)
Right (1,"")
λ> extractVarInt (packInteger 0x7f) :: VarInt.Okay (VarInt, ShortByteString)
Right (127,"")
λ> -- 8-bit and larger values have their MSB set until a zero MSB byte is found:
λ> extractVarInt (packInteger 0x8001) :: VarInt.Okay (VarInt, ShortByteString)
Right (128,"")
λ> extractVarInt (packInteger 0xff01) :: VarInt.Okay (VarInt, ShortByteString)
Right (255,"")
λ> extractVarInt (packInteger 0xac02) :: VarInt.Okay (VarInt, ShortByteString)
Right (300,"")
λ> extractVarInt (packInteger 0x808001) :: VarInt.Okay (VarInt, ShortByteString)
Right (16384,"")
Development
Unit tests are provided on the main ipfshs repo,
and bugs can be reported on ipfshs ticket tracker.
Licensing
The mfmts project and its modules are free software and licensed under the
AGPLv3 license. See
LICENSE.txt.
Copyright © 2026 Zoey McBride | zoeymcbride@mailbox.org