aboutsummaryrefslogblamecommitdiffstats
path: root/lib/merkle.ml
blob: 5b30856171c4c5a68edcdd09e696fe8d772c636c (plain) (tree)
1
2
3
4
5
6
7
8
9



                                                                                

                                                                             
 

                                                                             



                   
               
                       
 
                          
                               
 
                                           
                                                         
 
                                           
                                                         
 
                                              
                                       
 
                                         
                                   
 
                                                
                                                          
 
                     
                                       

   

                                                                        
                           
                                               
 
                     
 





                                                  





                                                                                  
                      
                                       

                                                                           

                                                                                                

                                                    
                              

   
               
                                           
(** Merkle tree module signature for content-addressed hash sets.

    This is an opaque interface that can be backed by different implementations:
    - A simple hash set (current placeholder)
    - A proper radix/patricia merkle tree (e.g., plebeia when OCaml 5 support
      arrives)

    The tree stores hashes as keys (like a set) and computes a root hash from
    all contained elements. *)

module type S = sig
  type t

  val empty : t
  (** The empty tree *)

  val is_empty : t -> bool
  (** Check if tree is empty *)

  val insert : Conventions.Hash.t -> t -> t
  (** Insert a hash into the tree. Returns a new tree. *)

  val delete : Conventions.Hash.t -> t -> t
  (** Delete a hash from the tree. Returns a new tree. *)

  val member : Conventions.Hash.t -> t -> bool
  (** Check if a hash is in the tree *)

  val keys : t -> Conventions.Hash.t list
  (** Get all hashes in the tree *)

  val root_hash : t -> Conventions.Hash.t option
  (** Compute the root hash of the tree. None if empty. *)

  val size : t -> int
  (** Number of elements in the tree *)
end

(** Simple hash set implementation. This is a placeholder until a proper
    radix-merkle library with OCaml 5 support becomes available. *)
module HashSet : S = struct
  module HashSet' = Set.Make (Conventions.Hash)

  type t = HashSet'.t

  let empty = HashSet'.empty
  let is_empty = HashSet'.is_empty
  let insert hash tree = HashSet'.add hash tree
  let delete hash tree = HashSet'.remove hash tree
  let member hash tree = HashSet'.mem hash tree
  let keys tree = HashSet'.elements tree
  (* TODO: Streaming/pagination for large tuple sets. Currently materializes
     entire keyset into memory, which fails for relations with billions of tuples.
     Replace with paginated access (keys_paginated offset limit) or lazy generator
     to avoid loading all hashes upfront. Consider replacing HashSet with proper
     radix-merkle tree (plebeia) for native lazy traversal. *)

  let root_hash tree =
    if HashSet'.is_empty tree then None
    else
      (* Compute root hash by hashing sorted concatenation of all hashes *)
      let sorted_hashes = HashSet'.elements tree in
      let concatenated = String.concat "" (List.map Conventions.Hash.to_string sorted_hashes) in
      Some (Conventions.Hash.hash_text concatenated)

  let size = HashSet'.cardinal
end

include HashSet
(** Default implementation using HashSet *)