···207207208208 val retrieve_node_raw : t -> Cid.t -> node_raw option Lwt.t
209209210210- val retrieve_node : t -> Cid.t -> node option Lwt.t
210210+ val retrieve_node : ?layer_hint:int -> t -> Cid.t -> node option Lwt.t
211211212212- val retrieve_node_lazy : t -> Cid.t -> node option Lwt.t lazy_t
212212+ val retrieve_node_lazy :
213213+ layer_hint:int -> t -> Cid.t -> node option Lwt.t lazy_t
213214214214- val get_node_height : t -> node_raw -> int Lwt.t
215215+ val get_node_height : ?layer_hint:int -> t -> node_raw -> int Lwt.t
215216216217 val traverse : t -> (string -> Cid.t -> unit) -> unit Lwt.t
217218···271272 | None ->
272273 Lwt.return_none
273274274274- (* retrieves & hydrates a node by cid *)
275275- let rec retrieve_node t cid : node option Lwt.t =
276276- match%lwt retrieve_node_raw t cid with
277277- | Some raw ->
278278- hydrate_node t raw |> Lwt.map Option.some
279279- | None ->
280280- Lwt.return_none
281281-282282- (* lazy version of retrieve_node *)
283283- and retrieve_node_lazy t cid = lazy (retrieve_node t cid)
275275+ (* returns the layer of a node, using hint if provided *)
276276+ let rec get_node_height ?layer_hint t node : int Lwt.t =
277277+ match layer_hint with
278278+ | Some layer ->
279279+ Lwt.return layer
280280+ | None -> (
281281+ match (node.l, node.e) with
282282+ | None, [] ->
283283+ Lwt.return 0
284284+ | Some left, [] -> (
285285+ match%lwt retrieve_node_raw t left with
286286+ | Some node ->
287287+ let%lwt height = get_node_height t node in
288288+ Lwt.return (height + 1)
289289+ | None ->
290290+ failwith ("couldn't find node " ^ Cid.to_string left) )
291291+ | _, leaf :: _ -> (
292292+ match leaf.p with
293293+ | 0 ->
294294+ Lwt.return (Util.leading_zeros_on_hash (Bytes.to_string leaf.k))
295295+ | _ ->
296296+ failwith "first node entry has nonzero p value" ) )
284297285298 (* hydrates a raw node *)
286286- and hydrate_node t node_raw : node Lwt.t =
299299+ let rec hydrate_node ?layer_hint t node_raw : node Lwt.t =
300300+ let%lwt layer = get_node_height ?layer_hint t node_raw in
301301+ let child_layer = layer - 1 in
287302 let left =
288303 match node_raw.l with
289304 | Some l ->
290290- retrieve_node_lazy t l
305305+ retrieve_node_lazy ~layer_hint:child_layer t l
291306 | None ->
292307 lazy Lwt.return_none
293308 in
294294- let%lwt layer = get_node_height t node_raw in
295309 let entries =
296310 List.fold_left
297311 (fun (entries : entry list) entry ->
···307321 let right =
308322 match entry.t with
309323 | Some r ->
310310- retrieve_node_lazy t r
324324+ retrieve_node_lazy ~layer_hint:child_layer t r
311325 | None ->
312326 lazy Lwt.return_none
313327 in
···316330 in
317331 Lwt.return {layer; left; entries}
318332319319- (* returns the layer of a node *)
320320- and get_node_height t node : int Lwt.t =
321321- match (node.l, node.e) with
322322- | None, [] ->
323323- Lwt.return 0
324324- | Some left, [] -> (
325325- match%lwt retrieve_node_raw t left with
326326- | Some node ->
327327- let%lwt height = get_node_height t node in
328328- Lwt.return (height + 1)
329329- | None ->
330330- failwith ("couldn't find node " ^ Cid.to_string left) )
331331- | _, leaf :: _ -> (
332332- match leaf.p with
333333- | 0 ->
334334- Lwt.return (Util.leading_zeros_on_hash (Bytes.to_string leaf.k))
335335- | _ ->
336336- failwith "first node entry has nonzero p value" )
333333+ (* retrieves & hydrates a node by cid *)
334334+ and retrieve_node ?layer_hint t cid : node option Lwt.t =
335335+ match%lwt retrieve_node_raw t cid with
336336+ | Some raw ->
337337+ hydrate_node ?layer_hint t raw |> Lwt.map Option.some
338338+ | None ->
339339+ Lwt.return_none
340340+341341+ and retrieve_node_lazy ~layer_hint t cid =
342342+ lazy (retrieve_node ~layer_hint t cid)
337343338344 (* calls fn with each entry's key and cid *)
339345 let traverse t fn : unit Lwt.t =
+12-29
pegasus/lib/repository.ml
···263263 : write_result Lwt.t =
264264 with_write_lock t.did (fun () ->
265265 let open Sequencer.Types in
266266- let module Inductive = Mist.Mst.Inductive (Mst) in
267266 let%lwt prev_commit =
268267 match%lwt User_store.get_commit t.db with
269268 | Some (_, commit) ->
···280279 Cid.to_string c
281280 | None ->
282281 "null" ) ) ;
283283- let%lwt block_map = Lwt.map ref (get_map t) in
284282 let cached_store = Cached_store.create t.db in
285283 let mst : Cached_mst.t ref =
286284 ref (Cached_mst.create cached_store prev_commit.data)
287285 in
286286+ t.block_map <- None ;
288287 (* ops to emit, built in loop because prev_data (previous cid) is otherwise inaccessible *)
289288 let commit_ops : commit_evt_op list ref = ref [] in
290289 let added_leaves = ref Block_map.empty in
···297296 let path = Format.sprintf "%s/%s" collection rkey in
298297 let uri = Format.sprintf "at://%s/%s" t.did path in
299298 let%lwt () =
300300- match String_map.find_opt path !block_map with
299299+ match%lwt User_store.get_record_cid t.db path with
301300 | Some cid ->
302301 Errors.invalid_request ~name:"InvalidSwap"
303302 (Format.sprintf
···314313 let%lwt cid, block =
315314 User_store.put_record t.db (`LexMap record_with_type) path
316315 in
317317- block_map := String_map.add path cid !block_map ;
318316 added_leaves := Block_map.set cid block !added_leaves ;
319317 commit_ops :=
320318 !commit_ops
···340338 | Update {collection; rkey; value; swap_record; _} ->
341339 let path = Format.sprintf "%s/%s" collection rkey in
342340 let uri = Format.sprintf "at://%s/%s" t.did path in
343343- let old_cid = String_map.find_opt path !block_map in
341341+ let%lwt old_cid = User_store.get_record_cid t.db path in
344342 ( if
345343 (swap_record <> None && swap_record <> old_cid)
346344 || (swap_record = None && old_cid = None)
···385383 User_store.put_record t.db (`LexMap record_with_type) path
386384 in
387385 added_leaves := Block_map.set new_cid new_block !added_leaves ;
388388- block_map := String_map.add path new_cid !block_map ;
389386 commit_ops :=
390387 !commit_ops
391388 @ [{action= `Update; path; cid= Some new_cid; prev= old_cid}] ;
···409406 ; cid= new_cid } )
410407 | Delete {collection; rkey; swap_record; _} ->
411408 let path = Format.sprintf "%s/%s" collection rkey in
412412- let cid = String_map.find_opt path !block_map in
409409+ let%lwt cid = User_store.get_record_cid t.db path in
413410 ( if cid = None || (swap_record <> None && swap_record <> cid)
414411 then
415412 let cid_str =
···441438 Lwt.return_unit
442439 in
443440 let%lwt () = User_store.delete_record t.db path in
444444- block_map := String_map.remove path !block_map ;
445441 commit_ops :=
446442 !commit_ops @ [{action= `Delete; path; cid= None; prev= cid}] ;
447443 let%lwt new_mst = Cached_mst.delete !mst path in
···458454 let commit_block =
459455 new_commit_signed |> signed_commit_to_yojson |> Dag_cbor.encode_yojson
460456 in
461461- let diff : Inductive.diff list =
462462- List.fold_left
463463- (fun (acc : Inductive.diff list)
464464- ({action; path; cid; prev} : commit_evt_op) ->
465465- match action with
466466- | `Create ->
467467- acc @ [Add {key= path; cid= Option.get cid}]
468468- | `Update ->
469469- acc @ [Update {key= path; cid= Option.get cid; prev}]
470470- | `Delete ->
471471- acc @ [Delete {key= path; prev= Option.get prev}] )
472472- [] !commit_ops
473473- in
474457 let%lwt proof_blocks =
475475- match%lwt
476476- Inductive.generate_proof !block_map diff ~new_root:new_mst.root
477477- ~prev_root:prev_commit.data
478478- with
479479- | Ok blocks ->
480480- Lwt.return (Block_map.merge blocks !added_leaves)
481481- | Error err ->
482482- raise err
458458+ Lwt_list.fold_left_s
459459+ (fun acc ({path; _} : commit_evt_op) ->
460460+ let%lwt key_proof =
461461+ Cached_mst.proof_for_key new_mst new_mst.root path
462462+ in
463463+ Lwt.return (Block_map.merge acc key_proof) )
464464+ Block_map.empty !commit_ops
483465 in
466466+ let proof_blocks = Block_map.merge proof_blocks !added_leaves in
484467 let block_stream =
485468 proof_blocks |> Block_map.entries |> Lwt_seq.of_list
486469 |> Lwt_seq.cons (new_commit_cid, commit_block)
+15
pegasus/lib/user_store.ml
···129129 ~cid ~data
130130131131 (* record storage *)
132132+ let get_record_cid =
133133+ [%rapper
134134+ get_opt
135135+ {sql| SELECT @CID{cid} FROM records WHERE path = %string{path} |sql}]
136136+137137+ let get_all_record_cids =
138138+ [%rapper get_many {sql| SELECT @string{path}, @CID{cid} FROM records |sql}]
139139+ ()
140140+132141 let get_record =
133142 [%rapper
134143 get_opt
···390399 Util.use_pool t.db @@ Queries.get_record ~path
391400 >|= Option.map (fun (cid, data, since) ->
392401 {path; cid; value= Lex.of_cbor data; since} )
402402+403403+let get_record_cid t path : Cid.t option Lwt.t =
404404+ Util.use_pool t.db @@ Queries.get_record_cid ~path
405405+406406+let get_all_record_cids t : (string * Cid.t) list Lwt.t =
407407+ Util.use_pool t.db Queries.get_all_record_cids
393408394409let get_records_by_cids t cids : (Cid.t * Blob.t) list Lwt.t =
395410 if List.is_empty cids then Lwt.return []