packages feed

dfinity-radix-tree-0.1.0: README.md

# dfinity-radix-tree: A generic data integrity layer.
[![Build Status](https://travis-ci.org/dfinity-lab/hs-radix-tree.svg?branch=master)](https://travis-ci.org/dfinity-lab/hs-radix-tree)
[![Hackage](https://img.shields.io/hackage/v/dfinity-radix-tree.svg)](https://hackage.haskell.org/package/dfinity-radix-tree)
[![Dependencies](https://img.shields.io/hackage-deps/v/dfinity-radix-tree.svg)](http://packdeps.haskellers.com/feed?needle=dfinity-radix-tree)
[![License: GPLv3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)

## Overview
This library allows you to construct a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree) on top of any underlying key–value database. It works by organizing your key–value pairs into a binary 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](http://hackage.haskell.org/package/leveldb-haskell) is already provided.
```haskell
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

import Control.Monad.Trans.Resource
import Database.LevelDB
import Network.DFINITY.RadixTree

instance MonadResource m => RadixDatabase (FilePath, Options) m DB where
   create = uncurry open
   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 define some simple type aliases and wrapper functions.
```haskell
import Control.Monad.Trans.Resource
import Data.ByteString
import Database.LevelDB
import Network.DFINITY.RadixTree

type MerkleTree = RadixTree DB
type MerkleRoot = RadixRoot

createMerkleTree
   :: MonadResource m
   => FilePath -- Database.
   -> Maybe MerkleRoot -- State root.
   -> m MerkleTree
createMerkleTree path root =
   createRadixTree bloomSize cacheSize root (path, options)
   where
   bloomSize = 262144
   cacheSize = 2048
   options = defaultOptions {createIfMissing = True}

insertMerkleTree
   :: MonadResource m
   => ByteString -- Key.
   -> ByteString -- Value.
   -> MerkleTree -- Tree.
   -> m MerkleTree
insertMerkleTree = insertRadixTree

deleteMerkleTree
   :: MonadResource m
   => ByteString -- Key.
   -> MerkleTree -- Tree.
   -> m MerkleTree
deleteMerkleTree = deleteRadixTree

merkleizeMerkleTree
   :: MonadResource m
   => MerkleTree -- Tree.
   -> m (MerkleRoot, MerkleTree)
merkleizeMerkleTree = merkleizeRadixTree

lookupMerkleTree
   :: MonadResource m
   => ByteString -- Key.
   -> MerkleTree -- Tree.
   -> m (Maybe (ByteString, MerkleTree))
lookupMerkleTree = lookupMerkleizedRadixTree
```
Using the API above, we can perform operations on the tree as a proxy for the database and see that its contents is uniquely defined by its `MerkleRoot`.

## Contribute

Feel free to join in. All are welcome. Open an [issue](https://github.com/dfinity-lab/hs-radix-tree/issues)!

## License

GPLv3