diff --git a/src/lib_base/operation.ml b/src/lib_base/operation.ml index 15ddeddac..6ebcc5080 100644 --- a/src/lib_base/operation.ml +++ b/src/lib_base/operation.ml @@ -40,6 +40,34 @@ let encoding = shell_header_encoding (obj1 (req "data" Variable.bytes))) +let bounded_encoding ?max_size () = + match max_size with + | None -> encoding + | Some max_size -> Data_encoding.check_size max_size encoding + +let bounded_list_encoding + ?max_length ?max_size ?max_operation_size ?max_pass () = + let open Data_encoding in + let op_encoding = bounded_encoding ?max_size:max_operation_size () in + let op_list_encoding = + match max_size with + | None -> + Variable.list ?max_length (dynamic_size op_encoding) + | Some max_size -> + check_size max_size + (Variable.list ?max_length (dynamic_size op_encoding)) in + obj2 + (req "operation_hashes_path" + (Operation_list_list_hash.bounded_path_encoding ?max_length:max_pass ())) + (req "operations" op_list_encoding) + +let bounded_hash_list_encoding ?max_length ?max_pass () = + let open Data_encoding in + obj2 + (req "operation_hashes_path" + (Operation_list_list_hash.bounded_path_encoding ?max_length:max_pass ())) + (req "operation_hashes" (Variable.list ?max_length Operation_hash.encoding)) + let pp fmt op = Data_encoding.Json.pp fmt (Data_encoding.Json.construct encoding op) diff --git a/src/lib_base/operation.mli b/src/lib_base/operation.mli index fe975a2d5..7a403e37d 100644 --- a/src/lib_base/operation.mli +++ b/src/lib_base/operation.mli @@ -20,3 +20,16 @@ type t = { include S.HASHABLE with type t := t and type hash := Operation_hash.t val of_bytes_exn: MBytes.t -> t + +val bounded_encoding: ?max_size:int -> unit -> t Data_encoding.t +val bounded_list_encoding: + ?max_length:int -> + ?max_size:int -> + ?max_operation_size:int -> + ?max_pass:int -> + unit -> (Operation_list_list_hash.path * t list) Data_encoding.t +val bounded_hash_list_encoding: + ?max_length:int -> + ?max_pass:int -> + unit -> (Operation_list_list_hash.path * Operation_hash.t list) Data_encoding.t + diff --git a/src/lib_crypto/blake2B.ml b/src/lib_crypto/blake2B.ml index faee6f2a4..b3a517515 100644 --- a/src/lib_crypto/blake2B.ml +++ b/src/lib_crypto/blake2B.ml @@ -274,6 +274,8 @@ module Generic_Merkle_tree (H : sig end +let rec log2 x = if x <= 1 then 0 else 1 + log2 ((x+1) / 2) + module Make_merkle_tree (R : sig val register_encoding: @@ -331,6 +333,13 @@ module Make_merkle_tree (fun () -> Op) ]) + let bounded_path_encoding ?max_length () = + match max_length with + | None -> path_encoding + | Some max_length -> + let max_depth = log2 max_length in + Data_encoding.check_size (max_depth * (size + 1) + 1) path_encoding + end include diff --git a/src/lib_crypto/s.ml b/src/lib_crypto/s.ml index 9f9865cc2..4ae75ed17 100644 --- a/src/lib_crypto/s.ml +++ b/src/lib_crypto/s.ml @@ -146,6 +146,7 @@ module type MERKLE_TREE = sig | Op val path_encoding: path Data_encoding.t + val bounded_path_encoding: ?max_length:int -> unit -> path Data_encoding.t val compute_path: elt list -> int -> path val check_path: path -> elt -> t * int diff --git a/src/lib_shell/distributed_db_message.ml b/src/lib_shell/distributed_db_message.ml index 28a95bb63..82fb4b050 100644 --- a/src/lib_shell/distributed_db_message.ml +++ b/src/lib_shell/distributed_db_message.ml @@ -27,6 +27,62 @@ module Bounded_encoding = struct let block_header = delayed (fun () -> !block_header_cache) let block_locator = delayed (fun () -> !block_locator_cache) + let operation_max_size = ref None + let operation_list_max_size = ref None + let operation_list_max_length = ref None + let operation_max_pass = ref None + + let operation_cache = + ref (Operation.bounded_encoding ?max_size:!operation_max_size ()) + let operation_list_cache = + ref (Operation.bounded_list_encoding + ?max_length:!operation_list_max_length + ?max_size:!operation_list_max_size + ?max_operation_size:!operation_max_size + ?max_pass:!operation_max_pass ()) + let operation_hash_list_cache = + ref (Operation.bounded_hash_list_encoding + ?max_length:!operation_list_max_length + ?max_pass:!operation_max_pass ()) + + let update_operation_list_encoding () = + operation_list_cache := + Operation.bounded_list_encoding + ?max_length:!operation_list_max_length + ?max_size:!operation_list_max_size + ?max_operation_size:!operation_max_size + ?max_pass:!operation_max_pass + () + let update_operation_hash_list_encoding () = + operation_list_cache := + Operation.bounded_list_encoding + ?max_length:!operation_list_max_length + ?max_pass:!operation_max_pass + () + let update_operation_encoding () = + operation_cache := + Operation.bounded_encoding ?max_size:!operation_max_size () + + let set_operation_max_size max = + operation_max_size := max ; + update_operation_encoding () ; + update_operation_list_encoding () + let set_operation_list_max_size max = + operation_list_max_size := max ; + update_operation_list_encoding () + let set_operation_list_max_length max = + operation_list_max_length := max ; + update_operation_list_encoding () ; + update_operation_hash_list_encoding () + let set_operation_max_pass max = + operation_max_pass := max ; + update_operation_list_encoding () ; + update_operation_hash_list_encoding () + + let operation = delayed (fun () -> !operation_cache) + let operation_list = delayed (fun () -> !operation_list_cache) + let operation_hash_list = delayed (fun () -> !operation_hash_list_cache) + end type t = @@ -136,7 +192,7 @@ let encoding = case ~tag:0x31 ~title:"Operation" - (obj1 (req "operation" Operation.encoding)) + (obj1 (req "operation" Bounded_encoding.operation)) (function Operation o -> Some o | _ -> None) (fun o -> Operation o); @@ -166,16 +222,16 @@ let encoding = case ~tag:0x51 ~title:"Operation_hashes_for_blocks" - (obj3 - (req "operation_hashes_for_block" - (obj2 - (req "hash" Block_hash.encoding) - (req "validation_pass" int8))) - (req "operation_hashes" (list Operation_hash.encoding)) - (req "operation_hashes_path" Operation_list_list_hash.path_encoding)) + (merge_objs + (obj1 + (req "operation_hashes_for_block" + (obj2 + (req "hash" Block_hash.encoding) + (req "validation_pass" int8)))) + Bounded_encoding.operation_hash_list) (function Operation_hashes_for_block (block, ofs, ops, path) -> - Some ((block, ofs), ops, path) | _ -> None) - (fun ((block, ofs), ops, path) -> + Some ((block, ofs), (path, ops)) | _ -> None) + (fun ((block, ofs), (path, ops)) -> Operation_hashes_for_block (block, ofs, ops, path)) ; case ~tag:0x60 @@ -192,16 +248,16 @@ let encoding = case ~tag:0x61 ~title:"Operations_for_blocks" - (obj3 - (req "operations_for_block" - (obj2 - (req "hash" Block_hash.encoding) - (req "validation_pass" int8))) - (req "operations" (list (dynamic_size Operation.encoding))) - (req "operations_path" Operation_list_list_hash.path_encoding)) + (merge_objs + (obj1 + (req "operations_for_block" + (obj2 + (req "hash" Block_hash.encoding) + (req "validation_pass" int8)))) + Bounded_encoding.operation_list) (function Operations_for_block (block, ofs, ops, path) -> - Some ((block, ofs), ops, path) | _ -> None) - (fun ((block, ofs), ops, path) -> + Some ((block, ofs), (path, ops)) | _ -> None) + (fun ((block, ofs), (path, ops)) -> Operations_for_block (block, ofs, ops, path)) ; ] diff --git a/src/lib_shell/distributed_db_message.mli b/src/lib_shell/distributed_db_message.mli index d44213dea..aa6ac631f 100644 --- a/src/lib_shell/distributed_db_message.mli +++ b/src/lib_shell/distributed_db_message.mli @@ -43,4 +43,8 @@ val pp_json : Format.formatter -> t -> unit module Bounded_encoding : sig val set_block_header_max_size: int option -> unit + val set_operation_max_size: int option -> unit + val set_operation_list_max_size: int option -> unit + val set_operation_list_max_length: int option -> unit + val set_operation_max_pass: int option -> unit end