P2P: allow to limit the size of operations and operations list

This commit is contained in:
Grégoire Henry 2018-06-02 17:13:57 +02:00 committed by Benjamin Canou
parent 8072d413fc
commit 99f6e40471
6 changed files with 130 additions and 19 deletions

View File

@ -40,6 +40,34 @@ let encoding =
shell_header_encoding shell_header_encoding
(obj1 (req "data" Variable.bytes))) (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 = let pp fmt op =
Data_encoding.Json.pp fmt Data_encoding.Json.pp fmt
(Data_encoding.Json.construct encoding op) (Data_encoding.Json.construct encoding op)

View File

@ -20,3 +20,16 @@ type t = {
include S.HASHABLE with type t := t include S.HASHABLE with type t := t
and type hash := Operation_hash.t and type hash := Operation_hash.t
val of_bytes_exn: MBytes.t -> 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

View File

@ -274,6 +274,8 @@ module Generic_Merkle_tree (H : sig
end end
let rec log2 x = if x <= 1 then 0 else 1 + log2 ((x+1) / 2)
module Make_merkle_tree module Make_merkle_tree
(R : sig (R : sig
val register_encoding: val register_encoding:
@ -331,6 +333,13 @@ module Make_merkle_tree
(fun () -> Op) (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 end
include include

View File

@ -146,6 +146,7 @@ module type MERKLE_TREE = sig
| Op | Op
val path_encoding: path Data_encoding.t 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 compute_path: elt list -> int -> path
val check_path: path -> elt -> t * int val check_path: path -> elt -> t * int

View File

@ -27,6 +27,62 @@ module Bounded_encoding = struct
let block_header = delayed (fun () -> !block_header_cache) let block_header = delayed (fun () -> !block_header_cache)
let block_locator = delayed (fun () -> !block_locator_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 end
type t = type t =
@ -136,7 +192,7 @@ let encoding =
case ~tag:0x31 case ~tag:0x31
~title:"Operation" ~title:"Operation"
(obj1 (req "operation" Operation.encoding)) (obj1 (req "operation" Bounded_encoding.operation))
(function Operation o -> Some o | _ -> None) (function Operation o -> Some o | _ -> None)
(fun o -> Operation o); (fun o -> Operation o);
@ -166,16 +222,16 @@ let encoding =
case ~tag:0x51 case ~tag:0x51
~title:"Operation_hashes_for_blocks" ~title:"Operation_hashes_for_blocks"
(obj3 (merge_objs
(obj1
(req "operation_hashes_for_block" (req "operation_hashes_for_block"
(obj2 (obj2
(req "hash" Block_hash.encoding) (req "hash" Block_hash.encoding)
(req "validation_pass" int8))) (req "validation_pass" int8))))
(req "operation_hashes" (list Operation_hash.encoding)) Bounded_encoding.operation_hash_list)
(req "operation_hashes_path" Operation_list_list_hash.path_encoding))
(function Operation_hashes_for_block (block, ofs, ops, path) -> (function Operation_hashes_for_block (block, ofs, ops, path) ->
Some ((block, ofs), ops, path) | _ -> None) Some ((block, ofs), (path, ops)) | _ -> None)
(fun ((block, ofs), ops, path) -> (fun ((block, ofs), (path, ops)) ->
Operation_hashes_for_block (block, ofs, ops, path)) ; Operation_hashes_for_block (block, ofs, ops, path)) ;
case ~tag:0x60 case ~tag:0x60
@ -192,16 +248,16 @@ let encoding =
case ~tag:0x61 case ~tag:0x61
~title:"Operations_for_blocks" ~title:"Operations_for_blocks"
(obj3 (merge_objs
(obj1
(req "operations_for_block" (req "operations_for_block"
(obj2 (obj2
(req "hash" Block_hash.encoding) (req "hash" Block_hash.encoding)
(req "validation_pass" int8))) (req "validation_pass" int8))))
(req "operations" (list (dynamic_size Operation.encoding))) Bounded_encoding.operation_list)
(req "operations_path" Operation_list_list_hash.path_encoding))
(function Operations_for_block (block, ofs, ops, path) -> (function Operations_for_block (block, ofs, ops, path) ->
Some ((block, ofs), ops, path) | _ -> None) Some ((block, ofs), (path, ops)) | _ -> None)
(fun ((block, ofs), ops, path) -> (fun ((block, ofs), (path, ops)) ->
Operations_for_block (block, ofs, ops, path)) ; Operations_for_block (block, ofs, ops, path)) ;
] ]

View File

@ -43,4 +43,8 @@ val pp_json : Format.formatter -> t -> unit
module Bounded_encoding : sig module Bounded_encoding : sig
val set_block_header_max_size: int option -> unit 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 end