···4848 match v with
4949 | `Map m ->
5050 if
5151- StringMap.mem "$type" m
5151+ (StringMap.mem "$type" m && StringMap.find "$type" m = `String "blob")
5252 || (StringMap.mem "cid" m && StringMap.mem "mimeType" m)
5353- || (StringMap.mem "size" m && StringMap.mem "mimeType" m)
5453 then `BlobRef (Blob_ref.of_ipld (`Map m))
5554 else `LexMap (StringMap.map of_ipld m)
5655 | `Array a ->
+28-22
mist/lib/mst.ml
···259259 let*? left = node.left in
260260 match left with Some l -> traverse l | None -> Lwt.return_unit
261261 in
262262- List.iter (fun (entry : entry) -> fn entry.key entry.value) node.entries ;
262262+ let%lwt () =
263263+ Lwt_list.iter_s
264264+ (fun (entry : entry) ->
265265+ fn entry.key entry.value ;
266266+ let*? right = entry.right in
267267+ match right with Some r -> traverse r | None -> Lwt.return_unit )
268268+ node.entries
269269+ in
263270 Lwt.return_unit
264271 in
265272 match%lwt retrieve_node t t.root with
···935942 in
936943 persist_from_sorted sorted >|= fun (root, _) -> {blockstore; root}
937944938938- (* insert or replace an entry, returning a new canonical mst
939939- doesn't persist changes *)
945945+ (* insert or replace an entry, returning a new canonical mst *)
940946 let add t key cid : t Lwt.t =
941947 Util.ensure_valid_key key ;
942948 let%lwt leaves = leaves_of_root t in
943949 let without = List.filter (fun (k, _) -> k <> key) leaves in
944950 of_assoc t.blockstore ((key, cid) :: without)
945951946946- (* delete an entry, returning a new canonical mst
947947- doesn't persist changes *)
952952+ (* delete an entry, returning a new canonical mst *)
948953 let delete t key : t Lwt.t =
949954 Util.ensure_valid_key key ;
950955 let%lwt leaves = leaves_of_root t in
···11081113end
1109111411101115module Inductive (M : Intf) = struct
11111111- module Mem_mst = Make (Memory_blockstore)
11161116+ module Cache_bs = Cache_blockstore (Memory_blockstore)
11171117+ module Mem_mst = Make (Cache_bs)
1112111811131119 type diff =
11141120 | Add of {key: string; cid: Cid.t}
···11161122 | Delete of {key: string; prev: Cid.t}
1117112311181124 (* given an mst diff, returns all new blocks as well as inductive proof blocks *)
11191119- let generate_proof (curr : M.t) (diff : diff list) (prev_root : Cid.t) :
11251125+ let generate_proof (map : Cid.t String_map.t) (diff : diff list)
11261126+ ~(new_root : Cid.t) ~(prev_root : Cid.t) :
11201127 ((Cid.t * bytes) list, exn) Lwt_result.t =
11211128 try%lwt
11221122- let%lwt map = M.build_map curr in
11231129 let%lwt mem_mst =
11241124- Mem_mst.of_assoc (Memory_blockstore.create ()) (String_map.bindings map)
11301130+ Mem_mst.of_assoc
11311131+ (Cache_bs.create (Memory_blockstore.create ()))
11321132+ (String_map.bindings map)
11251133 in
11261126- (* track all accessed cids relevant to inductive proof *)
11271127- let accessed_cids = ref Cid.Set.empty in
11281128- (* apply inverse of operations in reverse order *)
11291129- let%lwt new_mst, added_cids =
11341134+ (* save this now so we can read blocks from it later *)
11351135+ let block_map = mem_mst.blockstore.bs.blocks in
11361136+ (* apply inverse of operations in reverse order,
11371137+ check that mst root matches prev_root *)
11381138+ let%lwt inverted_mst, added_cids =
11301139 Lwt_list.fold_right_s
11311140 (fun (diff : diff) (mst, added_cids) ->
11321141 match diff with
11331142 | Delete {key; prev} | Update {key; prev= Some prev; _} ->
11341134- accessed_cids := Cid.Set.add prev !accessed_cids ;
11351143 let%lwt mst = Mem_mst.add mst key prev in
11361144 Lwt.return (mst, Cid.Set.remove prev added_cids)
11371145 | Add {key; cid} | Update {key; prev= None; cid} ->
11381138- accessed_cids := Cid.Set.add cid !accessed_cids ;
11391146 let%lwt mst = Mem_mst.delete mst key in
11401147 Lwt.return (mst, Cid.Set.add cid added_cids) )
11411148 diff (mem_mst, Cid.Set.empty)
11421149 in
11431143- if not (Cid.equal new_mst.root prev_root) then
11501150+ if not (Cid.equal inverted_mst.root prev_root) then
11441151 failwith
11451152 (Printf.sprintf
11461153 "inductive proof produced invalid previous cid: expected %s, got \
11471154 %s"
11481155 (Cid.to_string prev_root)
11491149- (Cid.to_string new_mst.root) ) ;
11561156+ (Cid.to_string inverted_mst.root) ) ;
11501157 let proof_cids =
11511151- Cid.Set.union added_cids !accessed_cids
11521152- |> Cid.Set.remove prev_root |> Cid.Set.add new_mst.root
11581158+ Cid.Set.union added_cids mem_mst.blockstore.reads
11591159+ |> Cid.Set.remove prev_root |> Cid.Set.add new_root
11531160 in
11541154- let%lwt {blocks= proof_bm; _} =
11551155- Memory_blockstore.get_blocks mem_mst.blockstore
11561156- (Cid.Set.elements proof_cids)
11611161+ let {blocks= proof_bm; _} : Block_map.with_missing =
11621162+ Block_map.get_many (Cid.Set.elements proof_cids) block_map
11571163 in
11581164 Lwt.return_ok (Block_map.entries proof_bm)
11591165 with e -> Lwt.return_error e
+2
mist/lib/storage/block_map.ml
···35353636let entries = Cid_map.bindings
37373838+let keys m = Cid_map.bindings m |> List.map fst
3939+3840let merge m m' =
3941 let m = Cid_map.fold (fun cid bytes m -> Cid_map.add cid bytes m) m m in
4042 Cid_map.fold (fun cid bytes m -> Cid_map.add cid bytes m) m' m
+37
mist/lib/storage/cache_blockstore.ml
···11+type 'bs data = {mutable reads: Cid.Set.t; bs: 'bs}
22+33+module Make
44+ (Bs : Blockstore.Writable) : sig
55+ include Blockstore.Writable
66+77+ val create : Bs.t -> t
88+end
99+with type t = Bs.t data = struct
1010+ type t = Bs.t data
1111+1212+ let create bs = {reads= Cid.Set.empty; bs}
1313+1414+ let get_bytes t cid =
1515+ match%lwt Bs.get_bytes t.bs cid with
1616+ | Some _ as res ->
1717+ t.reads <- Cid.Set.add cid t.reads ;
1818+ Lwt.return res
1919+ | None ->
2020+ Lwt.return_none
2121+2222+ let has t cid = Bs.has t.bs cid
2323+2424+ let get_blocks t cids =
2525+ let%lwt bm = Bs.get_blocks t.bs cids in
2626+ t.reads <-
2727+ Cid.Set.union t.reads (Cid.Set.of_list (Block_map.keys bm.blocks)) ;
2828+ Lwt.return bm
2929+3030+ let put_block t cid bytes = Bs.put_block t.bs cid bytes
3131+3232+ let put_many t blocks = Bs.put_many t.bs blocks
3333+3434+ let delete_block t cid = Bs.delete_block t.bs cid
3535+3636+ let delete_many t cids = Bs.delete_many t.bs cids
3737+end
+9
mist/lib/storage/storage.ml
···23232424 module Readable : Blockstore.Readable with type t = Impl.t = Impl
2525end
2626+2727+module Cache_blockstore (Bs : Blockstore.Writable) = struct
2828+ module Impl = Cache_blockstore.Make (Bs)
2929+ include Impl
3030+3131+ module Readable : Blockstore.Readable with type t = Impl.t = Impl
3232+3333+ module Writable : Blockstore.Writable with type t = Impl.t = Impl
3434+end
+6-1
pegasus/lib/repository.ml
···226226 User_store.put_commit t.db signed |> Lwt_result.get_exn
227227 in
228228 t.commit <- Some (commit_cid, signed) ;
229229+ (* clear cached blocks so next get_map call rebuilds from the new commit *)
230230+ t.block_map <- None ;
229231 Lwt.return (commit_cid, signed)
230232231233let put_initial_commit t : (Cid.t * signed_commit) Lwt.t =
···401403 [] !commit_ops
402404 in
403405 let%lwt proof_blocks =
404404- match%lwt Inductive.generate_proof new_mst diff prev_commit.data with
406406+ match%lwt
407407+ Inductive.generate_proof !block_map diff ~new_root:new_mst.root
408408+ ~prev_root:prev_commit.data
409409+ with
405410 | Ok blocks ->
406411 Lwt.return blocks
407412 | Error err ->
+3-1
pegasus/lib/xrpc.ml
···3838 try%lwt
3939 let%lwt body = Dream.body req in
4040 body |> Yojson.Safe.from_string |> of_yojson |> Result.get_ok |> Lwt.return
4141- with _ -> Errors.invalid_request "Invalid request body"
4141+ with e ->
4242+ Errors.log_exn e ;
4343+ Errors.invalid_request "Invalid request body"
42444345let service_proxy (ctx : context) (proxy_header : string) =
4446 let did = Auth.get_authed_did_exn ctx.auth in