···82828383 val build_map : t -> Cid.t StringMap.t Lwt.t
84848585- val path_to_entry : t -> Cid.t -> string -> (Cid.t * bytes) list Lwt.t
8686-8785 val to_blocks_stream : t -> (Cid.t * bytes) Lwt_seq.t
88868987 val serialize : t -> node -> (Cid.t * bytes, exn) Lwt_result.t
8888+8989+ val proof_for_key : t -> Cid.t -> string -> Block_map.t Lwt.t
90909191 val get_covering_proof : t -> string -> Storage.Block_map.t Lwt.t
9292···273273 in
274274 Lwt.return !map
275275276276- (* returns cids and blocks that form the path from a given node to a given entry *)
277277- let rec path_to_entry t node key : (Cid.t * bytes) list Lwt.t =
278278- let%lwt root_bytes = Store.get_bytes t.blockstore node in
279279- let%lwt root_raw =
280280- match root_bytes with
281281- | None ->
282282- Lwt.return_none
283283- | Some bytes ->
284284- Lwt.return_some (decode_block_raw bytes)
285285- in
286286- let%lwt root =
287287- match root_raw with
288288- | None ->
289289- Lwt.return_none
290290- | Some root ->
291291- hydrate_node t root |> Lwt.map Option.some
292292- in
293293- (* if there is a left child, try to find a path through the left subtree *)
294294- let%lwt path_through_left =
295295- match root_raw with
296296- | None ->
297297- Lwt.return_some []
298298- | Some raw -> (
299299- match raw.l with
300300- | None ->
301301- Lwt.return_none
302302- | Some left -> (
303303- match%lwt path_to_entry t left key with
304304- | [] ->
305305- Lwt.return_none
306306- | path ->
307307- (* Option.get is safe because root is Some only when root_bytes is Some *)
308308- Lwt.return_some (path @ [(node, Option.get root_bytes)]) ) )
309309- in
310310- match path_through_left with
311311- | Some path ->
312312- Lwt.return path
313313- | None -> (
314314- (* if a left subtree path couldn't be found, find the entry whose right subtree this key would belong to *)
315315- (* this branch is only reached when root/root_raw/root_bytes are not None;
316316- if they were, path_through_left would be Some [] *)
317317- let entries = (Option.get root).entries in
318318- let entries_len = List.length entries in
319319- let entry_index =
320320- match List.find_index (fun (e : entry) -> e.key >= key) entries with
321321- | Some index ->
322322- index
323323- | None ->
324324- entries_len
325325- in
326326- (* path_through_left is None -> root_bytes is Some *)
327327- let path_tail = [(node, Option.get root_bytes)] in
328328- (* entry_index here is actually the entry to the right of the subtree the key would belong to *)
329329- match entry_index with
330330- | _
331331- (* because entries[entry_index] might turn out to be the entry we're looking for *)
332332- when entry_index < entries_len
333333- && (List.nth entries entry_index).key = key ->
334334- Lwt.return path_tail
335335- | _ -> (
336336- (* otherwise, we continue down the right subtree of the entry before entry_index *)
337337- (* path_through_left is None -> root_raw is Some *)
338338- match Util.last (Option.get root_raw).e with
339339- | Some last when last.t <> None ->
340340- let%lwt path_through_right =
341341- (* when last.t <> None *)
342342- path_to_entry t (Option.get last.t) key
343343- in
344344- Lwt.return (path_through_right @ path_tail)
345345- | _ ->
346346- Lwt.return path_tail ) )
347347-348276 (* returns all mst entries in order for a car stream *)
349277 let to_blocks_stream t : (Cid.t * bytes) Lwt_seq.t =
350278 let module M = struct
···556484 let keys = node_entry_keys raw in
557485 let seq = interleave_raw raw keys in
558486 let index = find_gte_leaf_index key seq in
559559- let blocks_lwt =
487487+ let%lwt blocks =
560488 match Util.at_index index seq with
561561- | Some (Leaf (k, _, _)) when k = key ->
562562- Lwt.return Block_map.empty
489489+ | Some (Leaf (k, v, _)) when k = key -> (
490490+ (* include the found leaf block to prove existence *)
491491+ match%lwt Store.get_bytes t.blockstore v with
492492+ | Some leaf_bytes ->
493493+ Lwt.return (Block_map.set v leaf_bytes Block_map.empty)
494494+ | None ->
495495+ Lwt.return Block_map.empty )
563496 | _ -> (
564497 let prev =
565498 if index - 1 >= 0 then Util.at_index (index - 1) seq else None
···568501 | Some (Tree c) ->
569502 proof_for_key t c key
570503 | _ ->
571571- Lwt.return Block_map.empty )
504504+ (* include bounding neighbor leaf blocks (if any) to prove nonexistence *)
505505+ let left_leaf =
506506+ match prev with
507507+ | Some (Leaf (_, v_left, _)) ->
508508+ Some v_left
509509+ | _ ->
510510+ None
511511+ in
512512+ let right_leaf =
513513+ match Util.at_index index seq with
514514+ | Some (Leaf (_, v_right, _)) ->
515515+ Some v_right
516516+ | _ ->
517517+ None
518518+ in
519519+ let%lwt bm =
520520+ match left_leaf with
521521+ | Some cid_left -> (
522522+ match%lwt Store.get_bytes t.blockstore cid_left with
523523+ | Some b ->
524524+ Lwt.return
525525+ (Block_map.set cid_left b Block_map.empty)
526526+ | None ->
527527+ Lwt.return Block_map.empty )
528528+ | None ->
529529+ Lwt.return Block_map.empty
530530+ in
531531+ let%lwt bm =
532532+ match right_leaf with
533533+ | Some cid_right -> (
534534+ match%lwt Store.get_bytes t.blockstore cid_right with
535535+ | Some b ->
536536+ Lwt.return (Block_map.set cid_right b bm)
537537+ | None ->
538538+ Lwt.return bm )
539539+ | None ->
540540+ Lwt.return bm
541541+ in
542542+ Lwt.return bm )
572543 in
573573- let%lwt blocks = blocks_lwt in
574544 Lwt.return (Block_map.set cid bytes blocks)
575545576546 (* returns all mst nodes needed to prove the value of a given key's left sibling *)
···583553 let keys = node_entry_keys raw in
584554 let seq = interleave_raw raw keys in
585555 let index = find_gte_leaf_index key seq in
586586- let blocks_lwt =
556556+ let%lwt blocks =
587557 let prev =
588558 if index - 1 >= 0 then Util.at_index (index - 1) seq else None
589559 in
590560 match prev with
591561 | Some (Tree c) ->
592562 proof_for_left_sibling t c key
563563+ | Some (Leaf (_, v_left, _)) -> (
564564+ match%lwt Store.get_bytes t.blockstore v_left with
565565+ | Some b ->
566566+ Lwt.return (Block_map.set v_left b Block_map.empty)
567567+ | None ->
568568+ Lwt.return Block_map.empty )
593569 | _ ->
594570 Lwt.return Block_map.empty
595571 in
596596- let%lwt blocks = blocks_lwt in
597572 Lwt.return (Block_map.set cid bytes blocks)
598573599574 (* returns all mst nodes needed to prove the value of a given key's right sibling *)
···613588 | some ->
614589 some
615590 in
616616- let blocks_lwt =
591591+ let%lwt blocks =
617592 match found with
618593 | Some (Tree c) ->
619594 proof_for_right_sibling t c key
···626601 match neighbor with
627602 | Some (Tree c) ->
628603 proof_for_right_sibling t c key
604604+ | Some (Leaf (_, v_right, _)) -> (
605605+ match%lwt Store.get_bytes t.blockstore v_right with
606606+ | Some b ->
607607+ Lwt.return (Block_map.set v_right b Block_map.empty)
608608+ | None ->
609609+ Lwt.return Block_map.empty )
629610 | _ ->
630611 Lwt.return Block_map.empty )
631612 | None ->
632613 Lwt.return Block_map.empty
633614 in
634634- let%lwt blocks = blocks_lwt in
635615 Lwt.return (Block_map.set cid bytes blocks)
636616637617 (* a covering proof is all mst nodes needed to prove the value of a given leaf