   "Create a block by reading the source into memory and hashing it."
   [algorithm source]
   ; OPTIMIZE: calculate the hash while reading the content in one pass.
-  (let [hash-fn (or (multihash/functions algorithm)
-                    (throw (IllegalArgumentException.
-                             (str "No digest function found for algorithm "
-                                  algorithm))))
+  (let [hash-fn (hasher algorithm)
         content (collect-bytes source)
         size (count content)]
     (when (pos? size)

  (Instant/now))


(defn create-block
  "Create a block from a content reader. The simplest version is a no-arg
  function which should return a new `InputStream` to read the full block
  content. The block is given the id and size directly, without being checked."
  [id size stored-at content]
  (when-not (instance? Multihash id)
    (throw (ex-info "Block id must be a multihash"
                    {:id id, :size size, :stored-at stored-at})))
  (when-not (pos-int? size)
    (throw (ex-info "Block size must be a positive integer"
                    {:id id, :size size, :stored-at stored-at})))
  (when-not stored-at
    (throw (ex-info "Block must have a stored-at instant"
                    {:id id, :size size, :stored-at stored-at})))
  (when-not content
    (throw (ex-info "Block must have a content reader"
                    {:id id, :size size, :stored-at stored-at})))
  (Block. id size stored-at content nil 0))


(defn load-block

(ns ^:no-doc blocks.data
  "Block type and constructor functions.

  Blocks have two primary attributes, `:id` and `:size`. The block identifier
