A generic data integrity layer.
This library allows you to construct a 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.
dfinity-radix-tree: A generic data integrity layer.
Overview
This library allows you to construct a 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 is already provided.
{-# 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.
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
.
{-# 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.