Copyright | (c) Tochi Obudulu 2022 |
---|---|
License | BSD-3 |
Maintainer | tochicool@gmail.com |
Stability | experimental |
Portability | portable |
Safe Haskell | None |
Language | Haskell2010 |
Compact Sparse Merkle Trees
The
type represents a merkle tree of size
CompactSparseMerkleTree
i alg ai
containing elements of type a
authenticated with a secure cryptographic
hash function alg
. This allows for the novel generation and verification of
memory efficient cryptographic zero-knowledge proofs of inclusion and
exclusion of elements in the tree. Most operations require that a
be an
instance of the ByteArrayAccess
class and alg
be an instance of the
HashAlgorithm
class.
This module is intended to be imported qualified:
import Crypto.Hash.CompactSparseMerkleTree (CSMT) import qualified Crypto.Hash.CompactSparseMerkleTree as CSMT
Warning
The size of the tree obviously cannot exceed the size of the image of the
hash algorithm 2^(8 * hashDigestSize alg)
. The word length of the hash
digest for the algorithm must not exceed maxBound :: Int
. Violation of
these limits are not detected and a breach implies undefined behaviour.
Implementation
The implementation of CompactSparseMerkleTree
is based on compact sparse
merkle trees as described by:
- Faraz Haider. "Compact sparse merkle trees.", Cryptology ePrint Archive, October 2018, https://eprint.iacr.org/2018/955.
Asymptotic bounds for the average case time complexity are given with the
assumption that the supplied hash function acts as a random oracle under the
random oracle model and that the compact sparse merkle tree is valid
. In
practice, the probability that the observed complexity differs from the
average case is vanishingly small.
Additionally, this implementation enforces domain separation for the inputs
to the hash algorithm alg
to provide the proofs with resistance to second
preimage attacks. Inputs to hashes for leaf and parent nodes are prefixed
with the bytes 0x00
and 0x01
respectively before applying the hash
algorithm.
Synopsis
- type CSMT = CompactSparseMerkleTree
- data CompactSparseMerkleTree (i :: Size) alg a where
- data Size
- empty :: CSMT 'Empty alg a
- singleton :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT 'NonEmpty alg a
- fromList :: (ByteArrayAccess a, HashAlgorithm alg) => NonEmpty a -> CSMT 'NonEmpty alg a
- insert :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT i alg a -> CSMT 'NonEmpty alg a
- delete :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT i alg a -> (forall j. CSMT j alg a -> b) -> b
- lookup :: Digest alg -> CSMT i alg a -> Maybe a
- member :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT i alg a -> Bool
- notMember :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT i alg a -> Bool
- minimumDigest :: CSMT 'NonEmpty alg a -> Digest alg
- maximumDigest :: CSMT 'NonEmpty alg a -> Digest alg
- data MembershipProof alg = forall p. MembershipProof (Proof Direction p alg)
- data Proof d (p :: ProofType) alg where
- InclusionProof :: {..} -> Proof d 'Inclusion alg
- ExclusionProof :: {..} -> Proof d 'Exclusion alg
- data Direction
- data ProofType
- isInclusionProof :: MembershipProof alg -> Bool
- isExclusionProof :: MembershipProof alg -> Bool
- membershipProof :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT i alg a -> MembershipProof alg
- data MerkleRoot alg
- = EmptyMerkleRoot
- | MerkleRoot (Digest alg)
- merkleRoot :: CSMT i alg a -> MerkleRoot alg
- validProof :: HashAlgorithm alg => MerkleRoot alg -> MembershipProof alg -> Bool
- validInclusionProof :: HashAlgorithm alg => MerkleRoot alg -> Proof Direction 'Inclusion alg -> Bool
- validExclusionProof :: HashAlgorithm alg => MerkleRoot alg -> Proof Direction 'Exclusion alg -> Bool
- valid :: (ByteArrayAccess a, HashAlgorithm alg) => CSMT i alg a -> Bool
- depth :: (Num n, Ord n) => CSMT i alg a -> n
- toTree :: CSMT i alg a -> Maybe (Tree (DataNode alg a))
- drawTree :: Show a => CSMT i alg a -> String
CompactSparseMerkleTree Type
type CSMT = CompactSparseMerkleTree Source #
A compact sparse merkle tree of size i
with values a
authenticated over
the algorithm alg
.
data CompactSparseMerkleTree (i :: Size) alg a where Source #
A compact sparse merkle tree of size i
with values a
authenticated over
the algorithm alg
.
Instances
Foldable (CSMT i alg) Source # | |
Defined in Crypto.Hash.CompactSparseMerkleTree fold :: Monoid m => CSMT i alg m -> m # foldMap :: Monoid m => (a -> m) -> CSMT i alg a -> m # foldMap' :: Monoid m => (a -> m) -> CSMT i alg a -> m # foldr :: (a -> b -> b) -> b -> CSMT i alg a -> b # foldr' :: (a -> b -> b) -> b -> CSMT i alg a -> b # foldl :: (b -> a -> b) -> b -> CSMT i alg a -> b # foldl' :: (b -> a -> b) -> b -> CSMT i alg a -> b # foldr1 :: (a -> a -> a) -> CSMT i alg a -> a # foldl1 :: (a -> a -> a) -> CSMT i alg a -> a # toList :: CSMT i alg a -> [a] # null :: CSMT i alg a -> Bool # length :: CSMT i alg a -> Int # elem :: Eq a => a -> CSMT i alg a -> Bool # maximum :: Ord a => CSMT i alg a -> a # minimum :: Ord a => CSMT i alg a -> a # | |
Eq1 (CSMT i alg) Source # | |
Ord1 (CSMT i alg) Source # | |
Defined in Crypto.Hash.CompactSparseMerkleTree | |
Eq a => Eq (CSMT i alg a) Source # | |
Ord a => Ord (CSMT i alg a) Source # | |
Defined in Crypto.Hash.CompactSparseMerkleTree | |
Show a => Show (CSMT i alg a) Source # | |
The size of a compact sparse merkle tree.
Construction
singleton :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT 'NonEmpty alg a Source #
Create a singleton tree.
Worst case Θ(1).
fromList :: (ByteArrayAccess a, HashAlgorithm alg) => NonEmpty a -> CSMT 'NonEmpty alg a Source #
Create a tree from a list of elements.
Average case Θ(n*log n), Worst case Θ(n²) where n is the size of the tree.
Insertion
insert :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT i alg a -> CSMT 'NonEmpty alg a Source #
Insert an element in a tree. If the tree already contains an element whose hash is equal to the given value, it is replaced with the new value.
Average case Θ(log n), Worst case Θ(n) where n is the size of the tree.
Deletion
delete :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT i alg a -> (forall j. CSMT j alg a -> b) -> b Source #
Delete an element from a tree if such an element exists.
Average case Θ(log n), Worst case Θ(n) where n is the size of the tree.
Query
lookup :: Digest alg -> CSMT i alg a -> Maybe a Source #
Lookup the value with the digest in the map.
Average case Θ(log n), Worst case Θ(n) where n is the size of the tree.
member :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT i alg a -> Bool Source #
Is the element in the tree?
Average case Θ(log n), Worst case Θ(n) where n is the size of the tree.
notMember :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT i alg a -> Bool Source #
Is the element not in the tree?
Average case Θ(log n), Worst case Θ(n) where n is the size of the tree.
Min/Max
minimumDigest :: CSMT 'NonEmpty alg a -> Digest alg Source #
The minimum digest in the tree.
Average case Θ(log n), Worst case Θ(n) where n is the size of the tree.
maximumDigest :: CSMT 'NonEmpty alg a -> Digest alg Source #
The maximum digest in the tree.
Worst case Θ(1).
Proofs
data MembershipProof alg Source #
A membership proof over a hash algorithm alg
.
forall p. MembershipProof (Proof Direction p alg) |
Instances
Show (MembershipProof alg) Source # | |
Defined in Crypto.Hash.CompactSparseMerkleTree showsPrec :: Int -> MembershipProof alg -> ShowS # show :: MembershipProof alg -> String # showList :: [MembershipProof alg] -> ShowS # |
data Proof d (p :: ProofType) alg where Source #
A proof of p
with direction d
over a hash algorithm alg
.
InclusionProof | A proof of inclusion. |
ExclusionProof | A proof of exclusion. |
|
A type of proof
isInclusionProof :: MembershipProof alg -> Bool Source #
Is this an inclusion proof?
Worst case Θ(1).
isExclusionProof :: MembershipProof alg -> Bool Source #
Is this an exclusion proof?
Worst case Θ(1).
Proof construction
membershipProof :: (ByteArrayAccess a, HashAlgorithm alg) => a -> CSMT i alg a -> MembershipProof alg Source #
Construct a membership proof of inclusion if the given element is in the tree, or a proof of exclusion if the element is not in the tree.
Average case Θ(log n), Worst case Θ(n) where n is the size of the tree. The constructed membership proof has equivalent space complexity.
Proof verification
data MerkleRoot alg Source #
A merkle root of a tree.
EmptyMerkleRoot | A merkle root of an empty tree. |
MerkleRoot (Digest alg) | A merkle root of a non-empty tree. |
Instances
Eq (MerkleRoot alg) Source # | |
Defined in Crypto.Hash.CompactSparseMerkleTree (==) :: MerkleRoot alg -> MerkleRoot alg -> Bool # (/=) :: MerkleRoot alg -> MerkleRoot alg -> Bool # | |
Show (MerkleRoot alg) Source # | |
Defined in Crypto.Hash.CompactSparseMerkleTree showsPrec :: Int -> MerkleRoot alg -> ShowS # show :: MerkleRoot alg -> String # showList :: [MerkleRoot alg] -> ShowS # |
merkleRoot :: CSMT i alg a -> MerkleRoot alg Source #
The merkle root of a tree.
Worst case Θ(1).
validProof :: HashAlgorithm alg => MerkleRoot alg -> MembershipProof alg -> Bool Source #
Validate a membership proof against a merkle root.
Worst case Θ(d) where d is the number of hash digests in the membership proof.
validInclusionProof :: HashAlgorithm alg => MerkleRoot alg -> Proof Direction 'Inclusion alg -> Bool Source #
Validate an inclusion proof against a merkle root.
Worst case Θ(d) where d is the number of hash digests in the inclusion proof.
validExclusionProof :: HashAlgorithm alg => MerkleRoot alg -> Proof Direction 'Exclusion alg -> Bool Source #
Validate an exclusion proof against a merkle root.
Worst case Θ(d) where d is the number of hash digests in the exclusion proof.
valid :: (ByteArrayAccess a, HashAlgorithm alg) => CSMT i alg a -> Bool Source #
Validate a tree against the properties of a compact sparse merkle tree. Namely that:
- the maximum leaf digests for all subtrees are valid
- the leaf hash digests are valid
- and all leafs lie on its minimum distance path from the root.
All exported functions maintain these properties.
Average case Θ(n*log n), Worst case Θ(n²) where n is the size of the tree.
Debugging
depth :: (Num n, Ord n) => CSMT i alg a -> n Source #
The depth of a tree.
Average case Θ(n), Worst case Θ(n) where n is the size of the tree.