diff --git a/src/lib_crypto_dal/cryptobox.ml b/src/lib_crypto_dal/cryptobox.ml index a10c0345851f4fb8ed8d6ca9dceaba8e62f0f119..0651cfd3335bfd65928ddc4f5d906bf03efe26a3 100644 --- a/src/lib_crypto_dal/cryptobox.ml +++ b/src/lib_crypto_dal/cryptobox.ml @@ -281,7 +281,7 @@ module Inner = struct (* Domain for the FFT on erasure encoded slots (as polynomials). *) shard_size : int; (* Length of a shard in terms of scalar elements. *) - nb_pages : int; + pages_per_slot : int; (* Number of slot pages. *) page_length : int; remaining_bytes : int; @@ -346,9 +346,13 @@ module Inner = struct (req "slot_size" int31) (req "number_of_shards" uint16)) + let pages_per_slot {slot_size; page_size; _} = slot_size / page_size + (* Error cases of this functions are not encapsulated into `tzresult` for modularity reasons. *) - let make {redundancy_factor; slot_size; page_size; number_of_shards} = + let make + ({redundancy_factor; slot_size; page_size; number_of_shards} as + parameters) = let open Result_syntax in let k = slot_as_polynomial_length ~slot_size in let n = redundancy_factor * k in @@ -381,7 +385,7 @@ module Inner = struct domain_2k = make_domain (2 * k); domain_n = make_domain n; shard_size; - nb_pages = slot_size / page_size; + pages_per_slot = pages_per_slot parameters; page_length; remaining_bytes = page_size mod scalar_bytes_amount; evaluations_log; @@ -392,6 +396,10 @@ module Inner = struct in ensure_validity t + let parameters + ({redundancy_factor; slot_size; page_size; number_of_shards; _} : t) = + {redundancy_factor; slot_size; page_size; number_of_shards} + let polynomial_degree = Polynomials.degree let polynomial_evaluate = Polynomials.evaluate @@ -412,19 +420,19 @@ module Inner = struct else let offset = ref 0 in let res = Array.init t.k (fun _ -> Scalar.(copy zero)) in - for page = 0 to t.nb_pages - 1 do + for page = 0 to t.pages_per_slot - 1 do for elt = 0 to t.page_length - 1 do if !offset > t.slot_size then () else if elt = t.page_length - 1 then ( let dst = Bytes.create t.remaining_bytes in Bytes.blit slot !offset dst 0 t.remaining_bytes ; offset := !offset + t.remaining_bytes ; - res.((elt * t.nb_pages) + page) <- Scalar.of_bytes_exn dst) + res.((elt * t.pages_per_slot) + page) <- Scalar.of_bytes_exn dst) else let dst = Bytes.create scalar_bytes_amount in Bytes.blit slot !offset dst 0 scalar_bytes_amount ; offset := !offset + scalar_bytes_amount ; - res.((elt * t.nb_pages) + page) <- Scalar.of_bytes_exn dst + res.((elt * t.pages_per_slot) + page) <- Scalar.of_bytes_exn dst done done ; Ok res @@ -436,7 +444,7 @@ module Inner = struct let eval_coset t eval slot offset page = for elt = 0 to t.page_length - 1 do - let idx = (elt * t.nb_pages) + page in + let idx = (elt * t.pages_per_slot) + page in let coeff = Scalar.to_bytes (Array.get eval idx) in if elt = t.page_length - 1 then ( Bytes.blit coeff 0 slot !offset t.remaining_bytes ; @@ -452,7 +460,7 @@ module Inner = struct let eval = Evaluations.(evaluation_fft t.domain_k p |> to_array) in let slot = Bytes.init t.slot_size (fun _ -> '0') in let offset = ref 0 in - for page = 0 to t.nb_pages - 1 do + for page = 0 to t.pages_per_slot - 1 do eval_coset t eval slot offset page done ; slot @@ -803,7 +811,7 @@ module Inner = struct ]) let prove_page t p page_index = - if page_index < 0 || page_index >= t.nb_pages then + if page_index < 0 || page_index >= t.pages_per_slot then Error `Segment_index_out_of_range else let l = 1 lsl Z.(log2up (of_int t.page_length)) in @@ -816,42 +824,47 @@ module Inner = struct (* Parses the [slot_page] to get the evaluations that it contains. The evaluation points are given by the [slot_page_index]. *) let verify_page t cm {index = slot_page_index; content = slot_page} proof = - if slot_page_index < 0 || slot_page_index >= t.nb_pages then + if slot_page_index < 0 || slot_page_index >= t.pages_per_slot then Error `Segment_index_out_of_range else - let domain = Domains.build ~log:Z.(log2up (of_int t.page_length)) in - let slot_page_evaluations = - Array.init - (1 lsl Z.(log2up (of_int t.page_length))) - (function - | i when i < t.page_length - 1 -> - let dst = Bytes.create scalar_bytes_amount in - Bytes.blit - slot_page - (i * scalar_bytes_amount) - dst - 0 - scalar_bytes_amount ; - Scalar.of_bytes_exn dst - | i when i = t.page_length - 1 -> - let dst = Bytes.create t.remaining_bytes in - Bytes.blit - slot_page - (i * scalar_bytes_amount) - dst - 0 - t.remaining_bytes ; - Scalar.of_bytes_exn dst - | _ -> Scalar.(copy zero)) - in - Ok - (verify - t - cm - t.srs.kate_amortized_srs_g2_pages - domain - (Domains.get t.domain_k slot_page_index, slot_page_evaluations) - proof) + let expected_page_length = t.page_size in + let got_page_length = Bytes.length slot_page in + if expected_page_length <> got_page_length then + Error `Page_length_mismatch + else + let domain = Domains.build ~log:Z.(log2up (of_int t.page_length)) in + let slot_page_evaluations = + Array.init + (1 lsl Z.(log2up (of_int t.page_length))) + (function + | i when i < t.page_length - 1 -> + let dst = Bytes.create scalar_bytes_amount in + Bytes.blit + slot_page + (i * scalar_bytes_amount) + dst + 0 + scalar_bytes_amount ; + Scalar.of_bytes_exn dst + | i when i = t.page_length - 1 -> + let dst = Bytes.create t.remaining_bytes in + Bytes.blit + slot_page + (i * scalar_bytes_amount) + dst + 0 + t.remaining_bytes ; + Scalar.of_bytes_exn dst + | _ -> Scalar.(copy zero)) + in + Ok + (verify + t + cm + t.srs.kate_amortized_srs_g2_pages + domain + (Domains.get t.domain_k slot_page_index, slot_page_evaluations) + proof) end include Inner @@ -869,12 +882,4 @@ module Internal_for_tests = struct {srs_g1; srs_g2} let load_parameters parameters = initialisation_parameters := Some parameters - - let parameters (t : t) = - { - redundancy_factor = t.redundancy_factor; - slot_size = t.slot_size; - page_size = t.page_size; - number_of_shards = t.number_of_shards; - } end diff --git a/src/lib_crypto_dal/cryptobox.mli b/src/lib_crypto_dal/cryptobox.mli index 37c8e2b53178c563d3c7de47699256535b005fc0..afa68d7049ac8115568a4c841a788cbd57cf89f1 100644 --- a/src/lib_crypto_dal/cryptobox.mli +++ b/src/lib_crypto_dal/cryptobox.mli @@ -218,7 +218,4 @@ module Internal_for_tests : sig from test frameworks where tests with various parameters could be run using the same binary. *) val load_parameters : initialisation_parameters -> unit - - (** [parameters t] returns the parameters with which [t] was initialized. *) - val parameters : t -> parameters end diff --git a/src/lib_crypto_dal/cryptobox_intf.ml b/src/lib_crypto_dal/cryptobox_intf.ml index 95c0f4fb266c0a7a081fa1c6f9c8be65d9340939..825bc4f002efa7212b74cd0549c65fed84a739d2 100644 --- a/src/lib_crypto_dal/cryptobox_intf.ml +++ b/src/lib_crypto_dal/cryptobox_intf.ml @@ -65,6 +65,10 @@ module type VERIFIER = sig primitives defined in this module and stores them in a value of type [t] *) val make : parameters -> (t, [> `Fail of string]) result + (** [parameters t] returns the parameters given when [t] was + initialised with the function {!val:make} *) + val parameters : t -> parameters + (** Commitment to a polynomial. *) type commitment @@ -95,16 +99,21 @@ module type VERIFIER = sig (** An encoding for the proof of a page. *) val page_proof_encoding : page_proof Data_encoding.t - (** [verify_page t srs commitment page page_proof] returns [Ok - true] if the [proof] certifies that the [slot_page] is indeed - included in the slot committed with commitment - [commitment]. Returns [Ok false] otherwise. + (** [pages_per_slot t] returns the number of expected pages per slot. *) + val pages_per_slot : parameters -> int + + (** [verify_page t srs commitment page page_proof] returns [Ok true] + if the [proof] certifies that the [slot_page] is indeed included + in the slot committed with commitment [commitment]. Returns [Ok + false] otherwise. - Fails if the index of the page is out of range. *) + Fails if the index of the page is out of range or if the page is + not of the expected length [page_size] given for the + initialisation of [t]. *) val verify_page : t -> commitment -> page -> page_proof -> - (bool, [> `Segment_index_out_of_range]) Result.t + (bool, [> `Segment_index_out_of_range | `Page_length_mismatch]) Result.t end diff --git a/src/lib_protocol_environment/environment_V7.ml b/src/lib_protocol_environment/environment_V7.ml index b77c5e9c06c79632dfc512b4e2ca87c69658faad..4f6d306d995289a9b50a3c08c9078d15cee8279b 100644 --- a/src/lib_protocol_environment/environment_V7.ml +++ b/src/lib_protocol_environment/environment_V7.ml @@ -1398,5 +1398,14 @@ struct module Equality_witness = Environment_context.Equality_witness module Plonk = Tezos_protocol_environment_structs.V7.Plonk - module Dal = Tezos_crypto_dal.Cryptobox.Verifier + + module Dal = struct + include Tezos_crypto_dal.Cryptobox.Verifier + + let verify_page t sh page proof = + match verify_page t sh page proof with + | Error `Page_length_mismatch -> Ok false + | Error `Segment_index_out_of_range -> Error `Segment_index_out_of_range + | Ok r -> Ok r + end end diff --git a/src/lib_protocol_environment/sigs/v8.ml b/src/lib_protocol_environment/sigs/v8.ml index 40ed1bd693f8b521dc80651bc7a20cce7045c316..e494e59c5432fcebbbb9a35de1d115e3860621f7 100644 --- a/src/lib_protocol_environment/sigs/v8.ml +++ b/src/lib_protocol_environment/sigs/v8.ml @@ -11913,6 +11913,10 @@ val parameters_encoding : parameters Data_encoding.t defined in this module and store them in a value of type [t] *) val make : parameters -> (t, [> `Fail of string]) result +(** [parameters t] returns the parameters given when [t] was + initialised with the function {!val:make} *) +val parameters : t -> parameters + (** Commitment to a polynomial. *) type commitment @@ -11961,20 +11965,23 @@ type page_proof (** An encoding for the proof of a page. *) val page_proof_encoding : page_proof Data_encoding.t -(** [verify_page t commitment page page_proof] returns [Ok - true] if the [proof] certifies that the [slot_page] is indeed - included in the slot committed with commitment - [commitment]. Returns [Ok false] otherwise. +(** [pages_per_slot t] returns the number of expected pages per slot. *) +val pages_per_slot : parameters -> int + +(** [verify_page t srs commitment page page_proof] returns [Ok true] + if the [proof] certifies that the [slot_page] is indeed included + in the slot committed with commitment [commitment]. Returns [Ok + false] otherwise. - Fails if the index of the page is out of range. *) + Fails if the index of the page is out of range or if the page is + not of the expected length [page_size] given for the + initialisation of [t]. *) val verify_page : t -> commitment -> page -> page_proof -> - ( bool, - [> `Degree_exceeds_srs_length of string | `Segment_index_out_of_range] ) - Result.t + (bool, [> `Segment_index_out_of_range | `Page_length_mismatch]) Result.t end # 136 "v8.in.ml" diff --git a/src/lib_protocol_environment/sigs/v8/dal.mli b/src/lib_protocol_environment/sigs/v8/dal.mli index a81d669d7c796dc91eb1aa8ea26d9388366af603..7950e6e1ea2055c46e1b43d0322a43f6a49d7caf 100644 --- a/src/lib_protocol_environment/sigs/v8/dal.mli +++ b/src/lib_protocol_environment/sigs/v8/dal.mli @@ -41,6 +41,10 @@ val parameters_encoding : parameters Data_encoding.t defined in this module and store them in a value of type [t] *) val make : parameters -> (t, [> `Fail of string]) result +(** [parameters t] returns the parameters given when [t] was + initialised with the function {!val:make} *) +val parameters : t -> parameters + (** Commitment to a polynomial. *) type commitment @@ -89,17 +93,20 @@ type page_proof (** An encoding for the proof of a page. *) val page_proof_encoding : page_proof Data_encoding.t -(** [verify_page t commitment page page_proof] returns [Ok - true] if the [proof] certifies that the [slot_page] is indeed - included in the slot committed with commitment - [commitment]. Returns [Ok false] otherwise. +(** [pages_per_slot t] returns the number of expected pages per slot. *) +val pages_per_slot : parameters -> int + +(** [verify_page t srs commitment page page_proof] returns [Ok true] + if the [proof] certifies that the [slot_page] is indeed included + in the slot committed with commitment [commitment]. Returns [Ok + false] otherwise. - Fails if the index of the page is out of range. *) + Fails if the index of the page is out of range or if the page is + not of the expected length [page_size] given for the + initialisation of [t]. *) val verify_page : t -> commitment -> page -> page_proof -> - ( bool, - [> `Degree_exceeds_srs_length of string | `Segment_index_out_of_range] ) - Result.t + (bool, [> `Segment_index_out_of_range | `Page_length_mismatch]) Result.t diff --git a/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml b/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml index f988042e4372f2227ed33ddbf009c65d50c7af2a..eabf13ed0045d21d089ccd1cfb9d643c6b6f7043 100644 --- a/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml +++ b/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml @@ -230,7 +230,7 @@ let download_and_save_slots @@ Bitset.inter subscribed_slots_indexes confirmed_slots_indexes in let params = protocol_constants.parametric.dal.cryptobox_parameters in - let number_of_pages = params.slot_size / params.page_size in + let number_of_pages = Dal.Page.pages_per_slot params in (* DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/2766. As part of the clean rollup storage workflow, we should make sure that pages for old slots are removed from the storage when not needed anymore. diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index 629fd3e63e808f210f143a8bea55c1837ace07a2..91041cab3b547ac0765ee0a01caf0e5881b385cd 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -60,7 +60,7 @@ let sc_rollup_timeout_period_in_blocks = 20_160 Think harder about those values. *) let default_cryptobox_parameters = { - Dal.Slots_history.page_size = 4096; + Dal.page_size = 4096; slot_size = 1 lsl 20; redundancy_factor = 16; number_of_shards = 2048; @@ -276,7 +276,7 @@ let constants_mainnet = let derive_cryptobox_parameters ~redundancy_factor ~mainnet_constants_divider = let m = default_cryptobox_parameters in { - Dal.Slots_history.redundancy_factor; + Dal.redundancy_factor; page_size = m.page_size / mainnet_constants_divider; slot_size = m.slot_size / mainnet_constants_divider; number_of_shards = m.number_of_shards / mainnet_constants_divider; diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 1edf9aa6825f185bbacf2ed3754c09c395bf6bbe..2e60209824c16fa5c2c5862cfd55cc7da1e07810 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -97,6 +97,8 @@ module Sc_rollup = struct end module Dal = struct + include Dal_slot_repr + module Slot_index = struct include Dal_slot_repr.Index end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index f04a6959c5d85dc24af902d147726dac065a0e8a..8c838787e5225fb35cd81f82b03b92737ffe1bd0 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2782,6 +2782,13 @@ end (** This module exposes definitions for the data-availability layer. *) module Dal : sig + type parameters = Dal.parameters = { + redundancy_factor : int; + page_size : int; + slot_size : int; + number_of_shards : int; + } + (** This module re-exports definitions from {!Dal_slot_repr.Index}. *) module Slot_index : sig type t @@ -2822,6 +2829,8 @@ module Dal : sig module Page : sig type content = bytes + val pages_per_slot : parameters -> int + module Index : sig type t = int @@ -2904,13 +2913,6 @@ module Dal : sig Slot.Header.t list -> (t * History_cache.t) tzresult - type dal_parameters = Dal.parameters = { - redundancy_factor : int; - page_size : int; - slot_size : int; - number_of_shards : int; - } - type proof end diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index 7448c9ce5a6095df36f2c886d53d9246edb7e40c..bb7d89917a92405e012a3070d88d580a6d39a991 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -23,6 +23,15 @@ (* *) (*****************************************************************************) +type parameters = Dal.parameters = { + redundancy_factor : int; + page_size : int; + slot_size : int; + number_of_shards : int; +} + +let parameters_encoding = Dal.parameters_encoding + module Commitment = struct (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3389 @@ -120,6 +129,8 @@ module Page = struct type slot_index = Index.t + let pages_per_slot = Dal.pages_per_slot + module Index = struct type t = int @@ -586,15 +597,6 @@ module History = struct pp_inclusion_proof next_inc_proof - type dal_parameters = Dal.parameters = { - redundancy_factor : int; - page_size : int; - slot_size : int; - number_of_shards : int; - } - - let dal_parameters_encoding = Dal.parameters_encoding - type error += Dal_proof_error of string let () = @@ -631,9 +633,12 @@ module History = struct "Wrong page content for the given page index and slot commitment" | Error `Segment_index_out_of_range -> fail_with_error_msg "Segment_index_out_of_range" - | Error (`Degree_exceeds_srs_length s) -> + | Error `Page_length_mismatch -> fail_with_error_msg - @@ Format.sprintf "Degree_exceeds_srs_length: %s" s + @@ Format.sprintf + "Page_length_mismatch: Expected:%d. Got: %d" + dal_params.page_size + (Bytes.length page.content) let produce_proof dal_params page_id ~page_info slots_hist hist_cache = let open Lwt_tzresult_syntax in diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index cb39a47ea04c2a64a4c9eca23688a351f6219c42..a17d2d713a2a714038c32800343962189d4eb439 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -23,6 +23,19 @@ (* *) (*****************************************************************************) +(** To verify the proof of a page membership in its associated slot, the + Cryptobox module needs the following Dal parameters. These are part of the + protocol's parameters. See {!Default_parameters.default_dal}. *) +type parameters = Dal.parameters = { + redundancy_factor : int; + page_size : int; + slot_size : int; + number_of_shards : int; +} + +(** An encoding for values of type {!parameters}. *) +val parameters_encoding : parameters Data_encoding.t + (** Slot header representation for the data-availability layer. {1 Overview} @@ -109,6 +122,8 @@ module Page : sig type slot_index = Index.t + val pages_per_slot : Dal.parameters -> int + module Index : sig type t = int @@ -242,19 +257,6 @@ module History : sig (** Pretty-printer for {!proof}. *) val pp_proof : Format.formatter -> proof -> unit - (** To verify the proof of a page membership in its associated slot, the - Cryptobox module needs the following Dal parameters. These are part of the - protocol's parameters. See {!Default_parameters.default_dal}. *) - type dal_parameters = Dal.parameters = { - redundancy_factor : int; - page_size : int; - slot_size : int; - number_of_shards : int; - } - - (** An encoding for values of type {!dal_parameters}. *) - val dal_parameters_encoding : dal_parameters Data_encoding.t - (** [produce_proof dal_parameters page_id page_info slots_hist hist_cache] produces a proof that either: - there exists a confirmed slot in the skip list that contains @@ -273,7 +275,7 @@ module History : sig the candidate slot (if any). *) val produce_proof : - dal_parameters -> + parameters -> Page.t -> page_info:(Page.content * Page.proof) option -> t -> @@ -291,7 +293,7 @@ module History : sig the candidate slot (if any). *) val verify_proof : - dal_parameters -> Page.t -> t -> proof -> Page.content option tzresult Lwt.t + parameters -> Page.t -> t -> proof -> Page.content option tzresult Lwt.t type error += Add_element_in_slots_skip_list_violates_ordering diff --git a/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml index d833c46adca50483d24332a022701f64033d15e1..221181ef6b0d03374907ec244adeec4970ef49b9 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml @@ -49,7 +49,7 @@ let mk_cryptobox dal_params = let open Result_syntax in let parameters = Cryptobox.Internal_for_tests.initialisation_parameters_from_slot_size - ~slot_size:dal_params.Hist.slot_size + ~slot_size:dal_params.S.slot_size in let () = Cryptobox.Internal_for_tests.load_parameters parameters in match Cryptobox.make dal_params with @@ -59,7 +59,7 @@ let mk_cryptobox dal_params = let derive_dal_parameters (reference : Cryptobox.parameters) ~redundancy_factor ~constants_divider = { - Hist.redundancy_factor; + S.redundancy_factor; page_size = reference.page_size / constants_divider; slot_size = reference.slot_size / constants_divider; number_of_shards = reference.number_of_shards / constants_divider;