# dfinity-radix-tree: A generic data integrity layer.
[![DFINITY][dfinity-shield]][dfinity]
[![Hackage][hackage-shield]][hackage]
[![Dependencies][deps-shield]][deps]
[![License: BSD 3-Clause][license-shield]][license]
## Overview
This library allows you to construct a [Merkle tree][wiki-merkle-tree] on top of
any underlying key-value database. It works by organizing your key-value pairs
into a binary [radix tree][wiki-radix-tree], which is well suited for storing
large dictionaries of fairly random keys, and is optimized for storing keys of
the same length.
## Usage
Define your database as an instance of the [`RadixDatabase`][] type class. An
instance for [LevelDB][hackage-leveldb-haskell] is already provided.
```haskell
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Control.Monad.IO.Class (MonadIO)
import Database.LevelDB (DB, defaultReadOptions, defaultWriteOptions, get, put)
import DFINITY.RadixTree
instance MonadIO m => RadixDatabase m DB where
load database = get database defaultReadOptions
store database = put database defaultWriteOptions
```
Create a [`RadixTree`][] that is parameterized by your database. If you want to
make things more explicit, then you can define a simple type alias and wrapper
function.
```haskell
import Control.Monad.Trans.Resource (MonadResource)
import Database.LevelDB (DB, Options(..), defaultOptions, open)
import DFINITY.RadixTree
type RadixTree' = RadixTree DB
createRadixTree'
:: MonadResource m
=> FilePath -- Database.
-> Maybe RadixRoot -- State root.
-> m RadixTree'
createRadixTree' file root = do
handle <- open file options
createRadixTree cacheSize root handle
where
cacheSize = 2048
options = defaultOptions { createIfMissing = True }
```
Using the definitions above, you can create a radix tree, perform some basic
operations on it, and see that its contents is uniquely defined by its
[`RadixRoot`][].
```haskell
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Resource (runResourceT)
import Data.ByteString.Base16 (encode)
import Data.ByteString.Char8 (unpack)
import Data.ByteString.Short (fromShort)
import DFINITY.RadixTree
main :: IO ()
main = runResourceT $ do
-- Create a radix tree, insert a key-value pair, and Merkleize.
tree <- createRadixTree' "/path/to/database" Nothing
tree' <- insertRadixTree "Hello" "World" tree
root <- fst <$> merkleizeRadixTree tree'
-- Print the state root.
liftIO $ putStrLn $ "State Root: 0x" ++ pretty root
where pretty = unpack . encode . fromShort
```
Running the program above should produce the following result.
```
State Root: 0xb638755216858bc84de8b80f480f15ca5c733e95
```
## License
`dfinity-radix-tree` is licensed under the [BSD 3-Clause License][license].
[//]: # (----------------------------------------------------------------------)
[dfinity]:
https://dfinity.org
[dfinity-shield]:
https://img.shields.io/badge/made%20by-DFINITY-29abe2.svg
[hackage]:
https://hackage.haskell.org/package/dfinity-radix-tree
[hackage-shield]:
https://img.shields.io/hackage/v/dfinity-radix-tree.svg
[deps]:
https://packdeps.haskellers.com/feed?needle=dfinity-radix-tree
[deps-shield]:
https://img.shields.io/hackage-deps/v/dfinity-radix-tree.svg
[license]:
https://en.wikipedia.org/wiki/BSD_licenses
[license-shield]:
https://img.shields.io/badge/license-BSD%203--Clause-29abe2.svg
[wiki-radix-tree]:
https://en.wikipedia.org/wiki/Radix_tree
[wiki-merkle-tree]:
https://en.wikipedia.org/wiki/Merkle_tree
[hackage-leveldb-haskell]:
https://hackage.haskell.org/package/leveldb-haskell
[`RadixDatabase`]:
https://hackage.haskell.org/package/dfinity-radix-tree/docs/DFINITY-RadixTree.html#t:RadixDatabase
[`RadixTree`]:
https://hackage.haskell.org/package/dfinity-radix-tree/docs/DFINITY-RadixTree.html#t:RadixTree
[`RadixRoot`]:
https://hackage.haskell.org/package/dfinity-radix-tree/docs/DFINITY-RadixTree.html#t:RadixRoot
[//]: # (----------------------------------------------------------------------)