From 7687b1c1b989c50bac0a0a727a10bfb649a4ca8a Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Thu, 22 Sep 2022 11:42:38 +0200 Subject: [PATCH 01/11] lib_crypto: expose page_proof equality between Cryptobox and Verifier --- src/lib_crypto_dal/cryptobox.mli | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lib_crypto_dal/cryptobox.mli b/src/lib_crypto_dal/cryptobox.mli index 9be137a21ddf..afa68d7049ac 100644 --- a/src/lib_crypto_dal/cryptobox.mli +++ b/src/lib_crypto_dal/cryptobox.mli @@ -61,14 +61,20 @@ type t type commitment +type page_proof + module Verifier : - VERIFIER with type parameters = parameters and type commitment = commitment + VERIFIER + with type parameters = parameters + and type commitment = commitment + and type page_proof = page_proof include VERIFIER with type t := t and type parameters := parameters and type commitment := commitment + and type page_proof := page_proof (** The primitives exposed in this modules require some preprocessing. This preprocessing generates data from an unknown -- GitLab From 88d68d7825ed4232a953fc04da1107339f2e1846 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Thu, 22 Sep 2022 17:20:28 +0200 Subject: [PATCH 02/11] lib_crypto: export Cryptobox.t's parameters for testing purpose --- src/lib_crypto_dal/cryptobox.ml | 8 ++++++++ src/lib_crypto_dal/cryptobox.mli | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/lib_crypto_dal/cryptobox.ml b/src/lib_crypto_dal/cryptobox.ml index 559e503a16df..617f88c95ad1 100644 --- a/src/lib_crypto_dal/cryptobox.ml +++ b/src/lib_crypto_dal/cryptobox.ml @@ -856,4 +856,12 @@ 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 afa68d7049ac..735e2bf6c169 100644 --- a/src/lib_crypto_dal/cryptobox.mli +++ b/src/lib_crypto_dal/cryptobox.mli @@ -218,4 +218,7 @@ 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] is initialized. *) + val parameters : t -> parameters end -- GitLab From 09883237714fb2d1656635bfa9a52d30735a89dd Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Thu, 22 Sep 2022 11:44:43 +0200 Subject: [PATCH 03/11] Tests: extend helper module Assert with function `is_ok` --- src/proto_alpha/lib_protocol/test/helpers/assert.ml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/proto_alpha/lib_protocol/test/helpers/assert.ml b/src/proto_alpha/lib_protocol/test/helpers/assert.ml index b0609e6506fe..9350839c633a 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/assert.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/assert.ml @@ -210,6 +210,11 @@ let is_error ~loc ~pp = function | Ok x -> failwith "Unexpected (Ok %a) (%s)" pp x loc | Error _ -> return_unit +let get_ok ~__LOC__ = function + | Ok r -> return r + | Error err -> + failwith "@[Unexpected error (%s): %a@]" __LOC__ pp_print_trace err + open Context (* Some asserts for account operations *) -- GitLab From 076e8ab26aee929aa9695c6ed6633135e250ef5a Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Thu, 22 Sep 2022 11:43:46 +0200 Subject: [PATCH 04/11] Proto/Dal: for tests, get the content of a Dal skip list --- src/proto_alpha/lib_protocol/dal_slot_repr.ml | 4 ++++ src/proto_alpha/lib_protocol/dal_slot_repr.mli | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index 754834f59cc1..6afc14534c2b 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -799,6 +799,10 @@ module Slots_history = struct ~dest:next_cell in return_none + + module Internal_for_tests = struct + let content = Skip_list.content + end end include V1 diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index e8c91883fc8f..191aeb444dd8 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -284,4 +284,8 @@ module Slots_history : sig *) val verify_proof : dal_parameters -> Page.t -> t -> proof -> Page.content option tzresult Lwt.t + + module Internal_for_tests : sig + val content : t -> slot + end end -- GitLab From 688dd787d8362c85ed78aceda035359a1e77957d Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Thu, 22 Sep 2022 17:22:13 +0200 Subject: [PATCH 05/11] Proto/Dal: export errors of Dal_slot_repr to match on them in tests --- src/proto_alpha/lib_protocol/dal_slot_repr.ml | 32 +++++++++---------- .../lib_protocol/dal_slot_repr.mli | 4 +++ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index 6afc14534c2b..70bed66c2b9f 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -259,6 +259,22 @@ module Slots_history = struct let basis = 2 end + type error += Add_element_in_slots_skip_list_violates_ordering + + let () = + register_error_kind + `Temporary + ~id:"Dal_slot_repr.add_element_in_slots_skip_list_violates_ordering" + ~title:"Add an element in slots skip list that violates ordering" + ~description: + "Attempting to add an element on top of the Dal confirmed slots skip \ + list that violates the ordering." + Data_encoding.unit + (function + | Add_element_in_slots_skip_list_violates_ordering -> Some () + | _ -> None) + (fun () -> Add_element_in_slots_skip_list_violates_ordering) + module Skip_list = struct include Skip_list_repr.Make (Skip_list_parameters) @@ -284,22 +300,6 @@ module Slots_history = struct let compare_lwt a b = Lwt.return @@ compare a b - type error += Add_element_in_slots_skip_list_violates_ordering - - let () = - register_error_kind - `Temporary - ~id:"Dal_slot_repr.add_element_in_slots_skip_list_violates_ordering" - ~title:"Add an element in slots skip list that violates ordering" - ~description: - "Attempting to add an element on top of the Dal confirmed slots skip \ - list that violates the ordering." - Data_encoding.unit - (function - | Add_element_in_slots_skip_list_violates_ordering -> Some () - | _ -> None) - (fun () -> Add_element_in_slots_skip_list_violates_ordering) - let next ~prev_cell ~prev_cell_ptr elt = let open Tzresult_syntax in let* () = diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index 191aeb444dd8..6dedcad3dba7 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -285,6 +285,10 @@ module Slots_history : sig val verify_proof : dal_parameters -> Page.t -> t -> proof -> Page.content option tzresult Lwt.t + type error += Add_element_in_slots_skip_list_violates_ordering + + type error += Dal_proof_error of string + module Internal_for_tests : sig val content : t -> slot end -- GitLab From 240a57b12714551b996f70ce506bbc1be9b4c126 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Mon, 26 Sep 2022 13:13:54 +0200 Subject: [PATCH 06/11] Proto/Dal: export pp_slot function --- src/proto_alpha/lib_protocol/dal_slot_repr.mli | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index 6dedcad3dba7..e90f7f3e5f2d 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -97,6 +97,8 @@ type slot = t val equal : t -> t -> bool +val pp_slot : Format.formatter -> t -> unit + type slot_index = Index.t (** A DAL slot is decomposed to a successive list of pages with fixed content @@ -291,5 +293,6 @@ module Slots_history : sig module Internal_for_tests : sig val content : t -> slot + end end -- GitLab From b610e4a64e1ba217ddd8b7e5a6e23a84a1d1d52a Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Fri, 23 Sep 2022 15:49:40 +0200 Subject: [PATCH 07/11] Proto/Dal: expose types&functions in Internal_for_tests needed for tests --- src/proto_alpha/lib_protocol/dal_slot_repr.ml | 6 ++++++ src/proto_alpha/lib_protocol/dal_slot_repr.mli | 1 + 2 files changed, 7 insertions(+) diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index 70bed66c2b9f..69224f9e9540 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -802,6 +802,12 @@ module Slots_history = struct module Internal_for_tests = struct let content = Skip_list.content + + let proof_is proof expected = + match (expected, proof) with + | `Confirmed, Page_confirmed _ | `Unconfirmed, Page_unconfirmed _ -> + true + | _ -> false end end diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index e90f7f3e5f2d..e75fdd522a0f 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -294,5 +294,6 @@ module Slots_history : sig module Internal_for_tests : sig val content : t -> slot + val proof_is : proof -> [`Confirmed | `Unconfirmed] -> bool end end -- GitLab From 31c1d4bcdde26ae3295e792b371f26277008e214 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Sat, 24 Sep 2022 10:25:19 +0200 Subject: [PATCH 08/11] Env/V8: expose type equality for Dal page_proof type --- src/lib_protocol_environment/environment_V8.ml | 1 + src/lib_protocol_environment/environment_V8.mli | 1 + 2 files changed, 2 insertions(+) diff --git a/src/lib_protocol_environment/environment_V8.ml b/src/lib_protocol_environment/environment_V8.ml index 790a60592bf9..fef745a7caed 100644 --- a/src/lib_protocol_environment/environment_V8.ml +++ b/src/lib_protocol_environment/environment_V8.ml @@ -102,6 +102,7 @@ module type T = sig * Tezos_protocol_environment_structs.V8.Plonk.transcript and type Dal.parameters = Tezos_crypto_dal.Cryptobox.Verifier.parameters and type Dal.commitment = Tezos_crypto_dal.Cryptobox.Verifier.commitment + and type Dal.page_proof = Tezos_crypto_dal.Cryptobox.Verifier.page_proof and type Bounded.Non_negative_int32.t = Tezos_base.Bounded.Non_negative_int32.t and type Wasm_2_0_0.input = Tezos_scoru_wasm.Wasm_pvm_sig.input_info diff --git a/src/lib_protocol_environment/environment_V8.mli b/src/lib_protocol_environment/environment_V8.mli index 1bd5467e8504..e129d3958f7f 100644 --- a/src/lib_protocol_environment/environment_V8.mli +++ b/src/lib_protocol_environment/environment_V8.mli @@ -102,6 +102,7 @@ module type T = sig * Tezos_protocol_environment_structs.V8.Plonk.transcript and type Dal.parameters = Tezos_crypto_dal.Cryptobox.Verifier.parameters and type Dal.commitment = Tezos_crypto_dal.Cryptobox.Verifier.commitment + and type Dal.page_proof = Tezos_crypto_dal.Cryptobox.Verifier.page_proof and type Bounded.Non_negative_int32.t = Tezos_base.Bounded.Non_negative_int32.t and type Wasm_2_0_0.input = Tezos_scoru_wasm.Wasm_pvm_sig.input_info -- GitLab From b61e524a20d496a5d222a342cf9b29280927723c Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Tue, 27 Sep 2022 16:04:10 +0200 Subject: [PATCH 09/11] Proto/Tezt: add helper functions to test DAL refutation. --- manifest/main.ml | 1 + opam/tezos-alpha-test-helpers.opam | 1 + .../lib_protocol/test/helpers/dal_helpers.ml | 236 ++++++++++++++++++ .../lib_protocol/test/helpers/dune | 6 +- 4 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml diff --git a/manifest/main.ml b/manifest/main.ml index 1db41defd040..b5f97ff83a23 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -4171,6 +4171,7 @@ module Protocol = Protocol plugin |> if_some |> open_; octez_shell_services |> open_; plompiler |> if_ N.(number >= 015); + octez_crypto_dal |> if_ N.(number >= 016) |> open_; ] in let _plugin_tests = diff --git a/opam/tezos-alpha-test-helpers.opam b/opam/tezos-alpha-test-helpers.opam index 524c3b558b80..27fdb9af22ef 100644 --- a/opam/tezos-alpha-test-helpers.opam +++ b/opam/tezos-alpha-test-helpers.opam @@ -21,6 +21,7 @@ depends: [ "tezos-protocol-plugin-alpha" "tezos-shell-services" "tezos-plompiler" { >= "0.1.2" } + "tezos-crypto-dal" ] build: [ ["rm" "-r" "vendors"] diff --git a/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml new file mode 100644 index 000000000000..7ab32ea90627 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml @@ -0,0 +1,236 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +module S = Dal_slot_repr +module P = S.Page +module Hist = S.Slots_history +module Ihist = Hist.Internal_for_tests + +(* Some global constants. *) + +let genesis_history = Hist.genesis + +let genesis_history_cache = Hist.History_cache.empty ~capacity:3000L + +let level_one = Raw_level_repr.(succ root) + +let level_ten = Raw_level_repr.(of_int32_exn 10l) + +(* Helper functions. *) + +(** Error used below for functions that don't return their failures in the monad + error. *) +type error += Test_failure of string + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"test_failure" + ~title:"Test failure" + ~description:"Test failure." + ~pp:(fun ppf e -> Format.fprintf ppf "Test failure: %s" e) + (obj1 (req "error" string)) + (function Test_failure e -> Some e | _ -> None) + (fun e -> Test_failure e) + +(** Returns an object of type {!Cryptobox.t} from the given DAL paramters. *) +let dal_mk_env 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 + in + let () = Cryptobox.Internal_for_tests.load_parameters parameters in + match Cryptobox.make dal_params with + | Ok dal -> return dal + | Error (`Fail s) -> fail [Test_failure s] + +(** Returns the slot's polynomial from the given slot's data. *) +let dal_mk_polynomial_from_slot dal slot_data = + let open Result_syntax in + match Cryptobox.polynomial_from_slot dal slot_data with + | Ok p -> return p + | Error (`Slot_wrong_size s) -> + fail + [ + Test_failure + (Format.sprintf "polynomial_from_slot: Slot_wrong_size (%s)" s); + ] + +(** Using the given slot's polynomial, this function computes the page proof of + the page whose id is provided. *) +let dal_mk_prove_page dal polynomial page_id = + let open Result_syntax in + match Cryptobox.prove_page dal polynomial page_id.P.page_index with + | Ok p -> return p + | Error `Segment_index_out_of_range -> + fail [Test_failure "compute_proof_segment: Segment_index_out_of_range"] + +(** Constructs a slot whose ID is defined from the given level and given index, + and whose data are built using the given fill function. The function returns + the slot's data, polynomial and header (in the sense: id + kate + commitment). *) +let mk_slot ?(level = level_one) ?(index = S.Index.zero) + ?(fill_function = fun _i -> 'x') dal = + let open Result_syntax in + let params = Cryptobox.Internal_for_tests.parameters dal in + let slot_data = Bytes.init params.slot_size fill_function in + let* polynomial = dal_mk_polynomial_from_slot dal slot_data in + let kate_commit = Cryptobox.commit dal polynomial in + return + ( slot_data, + polynomial, + S.{id = S.{published_level = level; index}; header = kate_commit} ) + +(** Constructs a record value of type Page.id. *) +let mk_page_id published_level slot_index page_index = + P.{slot_id = {published_level; index = slot_index}; page_index} + +let no_data = Some (fun ~default_char:_ _ -> None) + +(** Constructs a page whose level and slot indexes are those of the given slot + (except if level is redefined via [?level]), and whose page index and data + are given by arguments [page_index] and [mk_data]. If mk_data set to [No], + the function returns the pair (None, page_id). Otherwise, the page's `data` + and `proof` is computed, and the function returns (Some (data, proof), + page_id). *) +let mk_page_info ?(default_char = 'x') ?level ?(page_index = P.Index.zero) + ?(custom_data = None) dal (slot : S.t) polynomial = + let open Result_syntax in + let level = + match level with None -> slot.id.published_level | Some level -> level + in + let params = Cryptobox.Internal_for_tests.parameters dal in + let page_id = mk_page_id level slot.id.index page_index in + let* page_proof = dal_mk_prove_page dal polynomial page_id in + match custom_data with + | None -> + let page_data = Bytes.make params.page_size default_char in + return (Some (page_data, page_proof), page_id) + | Some mk_data -> ( + match mk_data ~default_char params.page_size with + | None -> return (None, page_id) + | Some page_data -> return (Some (page_data, page_proof), page_id)) + +(** Increment the given slot index. Returns zero in case of overflow. *) +let succ_slot_index index = + Option.value_f + S.Index.(of_int (to_int index + 1)) + ~default:(fun () -> S.Index.zero) + +(** Returns the char after [c]. Restarts from the char whose code is 0 if [c]'s + code is 255. *) +let next_char c = Char.(chr ((code c + 1) mod 255)) + +(* Some check functions. *) + +(** Check that/if the returned content is the expected one. *) +let assert_content_is ~__LOC__ ~expected returned = + Assert.equal + ~loc:__LOC__ + (Option.equal Bytes.equal) + "Returned %s doesn't match the expected one" + (fun fmt opt -> + match opt with + | None -> Format.fprintf fmt "" + | Some bs -> Format.fprintf fmt "" (Bytes.to_string bs)) + returned + expected + +(** Auxiliary test function used by both unit and PBT tests: This function + produces a proof from the given information and verifies the produced result, + if any. The result of each step is checked with [check_produce_result] and + [check_verify_result], respectively. *) +let produce_and_verify_proof ~check_produce ?check_verify dal skip_list cache + ~page_info ~page_id = + let open Lwt_result_syntax in + let params = Cryptobox.Internal_for_tests.parameters dal in + let*! res = + Hist.produce_proof + params + ~page_info:(fun _pid -> return page_info) + page_id + skip_list + cache + >|= Environment.wrap_tzresult + in + let* () = check_produce res page_info in + match check_verify with + | None -> return_unit + | Some check_verify -> + let*? proof, _input_opt = res in + let*! res = + Hist.verify_proof params page_id skip_list proof + >|= Environment.wrap_tzresult + in + check_verify res page_info + +let expected_data page_info proof_status = + match (page_info, proof_status) with + | Some (d, _p), `Confirmed -> Some d + | None, `Confirmed -> assert false + | _ -> None + +let proof_status_to_string = function + | `Confirmed -> "CONFIRMED" + | `Unconfirmed -> "UNCONFIRMED" + +let successful_check_produce_result ~__LOC__ proof_status res page_info = + let open Lwt_result_syntax in + let* proof, input_opt = Assert.get_ok ~__LOC__ res in + let* () = + if Hist.Internal_for_tests.proof_is proof proof_status then return_unit + else + failwith + "Expected to have a %s page proof. Got %a@." + (proof_status_to_string proof_status) + Hist.pp_proof + proof + in + assert_content_is + ~__LOC__ + input_opt + ~expected:(expected_data page_info proof_status) + +let failing_check_produce_result ~__LOC__ err_string res _page_info = + Assert.proto_error ~loc:__LOC__ res (function + | Hist.Dal_proof_error s -> String.equal s err_string + | _ -> false) + +let successful_check_verify_result ~__LOC__ proof_status res page_info = + let open Lwt_result_syntax in + let* content = Assert.get_ok ~__LOC__ res in + let expected = expected_data page_info proof_status in + assert_content_is ~__LOC__ ~expected content + +(** Checks if the two provided Page.proof are equal. *) +let eq_page_proof = + let bytes_opt_of_proof page_proof = + Data_encoding.Binary.to_bytes_opt P.proof_encoding page_proof + in + fun pp1 pp2 -> + Option.equal Bytes.equal (bytes_opt_of_proof pp1) (bytes_opt_of_proof pp2) diff --git a/src/proto_alpha/lib_protocol/test/helpers/dune b/src/proto_alpha/lib_protocol/test/helpers/dune index 9fb6dd17a57c..65309764c9d2 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/dune +++ b/src/proto_alpha/lib_protocol/test/helpers/dune @@ -18,7 +18,8 @@ tezos-protocol-environment tezos-protocol-plugin-alpha tezos-shell-services - tezos-plompiler) + tezos-plompiler + tezos-crypto-dal) (flags (:standard) -open Tezos_base.TzPervasives @@ -28,4 +29,5 @@ -open Tezos_protocol_alpha -open Tezos_client_alpha -open Tezos_protocol_plugin_alpha - -open Tezos_shell_services)) + -open Tezos_shell_services + -open Tezos_crypto_dal)) -- GitLab From cc27368aa7f206b2c7f1ede70457b319a44c0cc5 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Wed, 28 Sep 2022 15:00:40 +0200 Subject: [PATCH 10/11] Proto/Tests: Add some PBT tests for DAL refutation. --- manifest/main.ml | 3 + opam/tezos-protocol-alpha-tests.opam | 1 + src/proto_alpha/lib_protocol/test/pbt/dune | 18 +- .../test/pbt/test_dal_slot_proof.ml | 195 ++++++++++++++++++ 4 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/test/pbt/test_dal_slot_proof.ml diff --git a/manifest/main.ml b/manifest/main.ml index b5f97ff83a23..1b013ab8858c 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -3573,6 +3573,7 @@ end = struct (3, "test_refutation_game", N.(number >= 014)); (3, "test_carbonated_map", N.(number >= 013)); (3, "test_zk_rollup_encoding", N.(number >= 015)); + (2, "test_dal_slot_proof", N.(number >= 016)); ] |> List.filter_map (fun (i, n, b) -> if b then Some (i, n) else None) in @@ -3613,6 +3614,8 @@ end = struct benchmark |> if_some |> open_; benchmark_type_inference |> if_some |> open_; sc_rollup |> if_some |> if_ N.(number >= 015) |> open_; + octez_crypto_dal |> if_ N.(number >= 016) |> open_; + octez_base_test_helpers |> if_ N.(number >= 016) |> open_; ] ~dune in diff --git a/opam/tezos-protocol-alpha-tests.opam b/opam/tezos-protocol-alpha-tests.opam index 23930c85fbb2..0b2d0e29dcbe 100644 --- a/opam/tezos-protocol-alpha-tests.opam +++ b/opam/tezos-protocol-alpha-tests.opam @@ -26,6 +26,7 @@ depends: [ "tezos-test-helpers" {with-test} "alcotest" { with-test & >= "1.5.0" } "tezos-sc-rollup-alpha" {with-test} + "tezos-crypto-dal" {with-test} "tezos-client-base" {with-test} "tezos-protocol-environment" {with-test} "tezos-stdlib-unix" {with-test} diff --git a/src/proto_alpha/lib_protocol/test/pbt/dune b/src/proto_alpha/lib_protocol/test/pbt/dune index 72a2d61953b6..b0ff5d0b4036 100644 --- a/src/proto_alpha/lib_protocol/test/pbt/dune +++ b/src/proto_alpha/lib_protocol/test/pbt/dune @@ -16,7 +16,8 @@ test_sc_rollup_encoding test_refutation_game test_carbonated_map - test_zk_rollup_encoding) + test_zk_rollup_encoding + test_dal_slot_proof) (libraries tezos-base tezos-micheline @@ -30,7 +31,9 @@ tezos-benchmark tezos-benchmark-alpha tezos-benchmark-type-inference-alpha - tezos-sc-rollup-alpha) + tezos-sc-rollup-alpha + tezos-crypto-dal + tezos-base-test-helpers) (flags (:standard) -open Tezos_base.TzPervasives @@ -40,7 +43,9 @@ -open Tezos_alpha_test_helpers -open Tezos_benchmark_alpha -open Tezos_benchmark_type_inference_alpha - -open Tezos_sc_rollup_alpha)) + -open Tezos_sc_rollup_alpha + -open Tezos_crypto_dal + -open Tezos_base_test_helpers)) (rule (alias runtest) @@ -112,6 +117,11 @@ (package tezos-protocol-alpha-tests) (action (run %{dep:./test_zk_rollup_encoding.exe}))) +(rule + (alias runtest) + (package tezos-protocol-alpha-tests) + (action (run %{dep:./test_dal_slot_proof.exe}))) + (rule (alias runtest1) (action (run %{exe:liquidity_baking_pbt.exe}))) (rule (alias runtest1) (action (run %{exe:saturation_fuzzing.exe}))) @@ -139,3 +149,5 @@ (rule (alias runtest3) (action (run %{exe:test_carbonated_map.exe}))) (rule (alias runtest3) (action (run %{exe:test_zk_rollup_encoding.exe}))) + +(rule (alias runtest2) (action (run %{exe:test_dal_slot_proof.exe}))) diff --git a/src/proto_alpha/lib_protocol/test/pbt/test_dal_slot_proof.ml b/src/proto_alpha/lib_protocol/test/pbt/test_dal_slot_proof.ml new file mode 100644 index 000000000000..b53746411087 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/pbt/test_dal_slot_proof.ml @@ -0,0 +1,195 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: PBT for refutation proofs of Dal + Invocation: dune exec \ + src/proto_alpha/lib_protocol/test/pbt/test_dal_slot_proof.exe + Subject: Refutation proof-related functions of Dal +*) + +open Protocol +open Dal_helpers + +(* Introduce some intermediate types*) + +(** The slot is not confirmed (skipped) iff the boolean is [true]. *) +type slot_skipped = bool + +type slots = slot_skipped list + +type levels = slots list + +(** Given a list of {!levels}, where each element is of type {!slots} = {!slot} + list, and where each slot is a pair (bool, char), this function populates an + empty slots_history skip list and a corresponding history_cache as follows: + - the function starts from a given [start_level] (default is 1) + - levels are incremented by 2 (to allow having levels without confirmed slots + for test purpose). + - every element in the list of levels represents the slots of a single level. + - each slot of a given level is not confirmed iff the boolean is true. *) +let populate_slots_history dal (levels_data : levels) = + let open Result_syntax in + (* Make and insert a slot. *) + let add_slot level sindex (cell, cache, slots_info) skip_slot = + let index = + Option.value_f (S.Index.of_int sindex) ~default:(fun () -> assert false) + in + let* _data, poly, slot = mk_slot ~level ~index dal in + let* cell, cache = + if skip_slot then return (cell, cache) + else + Hist.add_confirmed_slots cell cache [slot] |> Environment.wrap_tzresult + in + return (cell, cache, (poly, slot, skip_slot) :: slots_info) + in + (* Insert the slots of a level. *) + let add_slots level accu slots_data = + (* We start at level one, and we skip even levels for test purpose (which + means that no DAL slot is confirmed for them). *) + let curr_level = + Int32.of_int (1 + (2 * level)) |> Raw_level_repr.of_int32_exn + in + List.fold_left_i_e (add_slot curr_level) accu slots_data + in + (* Insert the slots of all the levels. *) + let add_levels = List.fold_left_i_e add_slots in + add_levels (genesis_history, genesis_history_cache, []) levels_data + +(** This function returns the (correct) information of a page to +prove that it is confirmed, or None if the page's slot is skipped. *) +let request_confirmed_page dal (poly, slot, skip_slot) = + let open Result_syntax in + if skip_slot then + (* We cannot check that a page of an unconfirmed slot is confirmed. *) + return None + else + let* page_info, page_id = mk_page_info dal slot poly in + return @@ Some (page_info, page_id) + +(** This function returns information of a page to prove that it is unconfirmed, +if the page's slot is skipped, the information look correct (but the slot is not +confirmed). Otherwise, we increment the publish_level field to simulate a non +confirmed slot (as for even levels, no slot is confirmed. See +{!populate_slots_history}). *) +let request_unconfirmed_page dal (poly, slot, skip_slot) = + let open Result_syntax in + (* If the slot is unconfirmed, we test that a page belonging to it is not + confirmed. If the slot is confirmed, we check that the page of the + slot at the next level is unconfirmed (since we insert levels without + any confirmed slot). *) + let level = + if skip_slot then S.(slot.id.published_level) + else Raw_level_repr.succ S.(slot.id.published_level) + in + let* page_info, page_id = mk_page_info ~level dal slot poly in + return @@ Some (page_info, page_id) + +(** This helper function allows to test DAL's {!produce_proof} and {!verify_proof} +functions, using the data constructed from {!populate_slots_history} above. *) +let helper_check_pbt_pages dal last_cell last_cache slots_info ~page_to_request + ~check_produce ~check_verify = + let open Lwt_result_syntax in + List.iter_es + (fun item -> + let*? mk_test = page_to_request dal item in + match mk_test with + | None -> return_unit + | Some (page_info, page_id) -> + produce_and_verify_proof + dal + last_cell + last_cache + ~page_info + ~page_id + ~check_produce + ~check_verify) + slots_info + +(** Making some confirmation pages tests for slots that are confirmed. *) +let check_confirmed_pages dal last_cell last_cache slots_info = + helper_check_pbt_pages + dal + last_cell + last_cache + slots_info + ~page_to_request:request_confirmed_page + ~check_produce:(successful_check_produce_result ~__LOC__ `Confirmed) + ~check_verify:(successful_check_verify_result ~__LOC__ `Confirmed) + +(** Making some unconfirmation pages tests for slots that are confirmed. *) +let check_unconfirmed_pages dal last_cell last_cache slots_info = + helper_check_pbt_pages + dal + last_cell + last_cache + slots_info + ~page_to_request:request_unconfirmed_page + ~check_produce:(successful_check_produce_result ~__LOC__ `Unconfirmed) + ~check_verify:(successful_check_verify_result ~__LOC__ `Unconfirmed) + +(* The main test function. *) +let pbt_test_dal_pages dal (levels_data : levels) = + let open Lwt_result_syntax in + let*? last_cell, last_cache, slots_info = + populate_slots_history dal levels_data + in + let* () = check_confirmed_pages dal last_cell last_cache slots_info in + check_unconfirmed_pages dal last_cell last_cache slots_info + +let tests = + Result.value_f + (dal_mk_env + { + Hist.redundancy_factor = 16; + page_size = 4096 / 64; + slot_size = 1048576 / 64; + number_of_shards = 2048 / 64; + }) + ~default:(fun () -> + Format.eprintf "failed to initialize Cryptobox.t" ; + assert false) + |> fun dal -> + let gen_dal_config : levels QCheck2.Gen.t = + QCheck2.Gen.( + let nb_slots = pure 20 in + let nb_levels = pure 5 in + (* The slot is confirmed iff the boolean is true *) + let slot = bool in + let slots = list_size nb_slots slot in + list_size nb_levels slots) + in + [ + Tztest.tztest_qcheck2 + ~name:"Pbt tests: confirmed/unconfirmed pages" + ~count:2 + gen_dal_config + (pbt_test_dal_pages dal); + ] + +let () = + let tests = [("Dal slots refutation", tests)] in + Alcotest_lwt.run "Refutation_game" tests |> Lwt_main.run -- GitLab From 1ca268ea383eef9a4f9eda7a3aebdb18f4554fbd Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Thu, 22 Sep 2022 11:43:31 +0200 Subject: [PATCH 11/11] Proto/Tests: add some unit tests for DAL refutation. --- manifest/main.ml | 1 + src/proto_alpha/lib_protocol/test/unit/dune | 6 +- .../lib_protocol/test/unit/main.ml | 1 + .../test/unit/test_dal_slot_proof.ml | 445 ++++++++++++++++++ 4 files changed, 451 insertions(+), 2 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml diff --git a/manifest/main.ml b/manifest/main.ml index 1b013ab8858c..b5475a4f84e4 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -3640,6 +3640,7 @@ end = struct test_helpers |> if_some |> open_; alcotest_lwt; octez_stdlib |> if_ N.(number >= 013) |> open_; + octez_crypto_dal |> if_ N.(number >= 016) |> open_; ] ~dune: Dune. diff --git a/src/proto_alpha/lib_protocol/test/unit/dune b/src/proto_alpha/lib_protocol/test/unit/dune index b840f665aa69..7fabcf75d5e7 100644 --- a/src/proto_alpha/lib_protocol/test/unit/dune +++ b/src/proto_alpha/lib_protocol/test/unit/dune @@ -15,7 +15,8 @@ tezos-protocol-alpha tezos-alpha-test-helpers alcotest-lwt - tezos-stdlib) + tezos-stdlib + tezos-crypto-dal) (flags (:standard) -open Tezos_base.TzPervasives @@ -25,7 +26,8 @@ -open Tezos_client_alpha -open Tezos_protocol_alpha -open Tezos_alpha_test_helpers - -open Tezos_stdlib)) + -open Tezos_stdlib + -open Tezos_crypto_dal)) (rule (alias runtest) diff --git a/src/proto_alpha/lib_protocol/test/unit/main.ml b/src/proto_alpha/lib_protocol/test/unit/main.ml index c7964f3314dd..9df7b4fa13f7 100644 --- a/src/proto_alpha/lib_protocol/test/unit/main.ml +++ b/src/proto_alpha/lib_protocol/test/unit/main.ml @@ -86,5 +86,6 @@ let () = Unit_test.spec "compare operations" Test_compare_operations.tests; Unit_test.spec "Delegate_consensus_key.ml" Test_consensus_key.tests; Unit_test.spec "local_contexts" Test_local_contexts.tests; + Unit_test.spec "dal slot proof" Test_dal_slot_proof.tests; ] |> Lwt_main.run diff --git a/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml b/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml new file mode 100644 index 000000000000..fc2b6852ffe4 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml @@ -0,0 +1,445 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (dal slot proof) + Invocation: dune exec src/proto_alpha/lib_protocol/test/unit/main.exe \ + -- test "^\[Unit\] dal slot proof$" + Subject: These unit tests check proof-related functions of Dal slots +*) + +open Protocol +module S = Dal_slot_repr +module P = S.Page +module Hist = S.Slots_history +open Dal_helpers + +(* Tests to check insertion of slots in a dal skip list. *) + +(** Check insertion of a new slot in the given skip list. *) +let skip_list_ordering dal skip_list ~mk_level ~mk_slot_index ~check_result = + let open Lwt_result_syntax in + let {S.id; _} = Hist.Internal_for_tests.content skip_list in + let*? _data, _poly, slot = + mk_slot ~level:(mk_level id) ~index:(mk_slot_index id) dal + in + Hist.add_confirmed_slots_no_cache skip_list [slot] + |> Environment.wrap_tzresult |> check_result + +(** This test attemps to add a slot on top of genesis cell zero which would + breaks the ordering. In fact, confirmed slots' skip list is ordered by slots + ID: the slots' level should increase or the level be equal in which case the + slots' index should increase. In the test below, we attempt to insert a slot + where (published_level, slot_index) doesn't increase (is the same as the + genesis cell). *) +let insertion_breaks_skip_list_ordering dal () = + skip_list_ordering + dal + genesis_history + ~mk_level:(fun id -> id.S.published_level) + ~mk_slot_index:(fun id -> id.S.index) + ~check_result:(fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Hist.Add_element_in_slots_skip_list_violates_ordering -> true + | _ -> false)) + +(** This test attemps to add a slot on top of genesis cell zero which satisfies +the ordering. *) +let correct_insertion_in_skip_list_ordering_1 dal () = + let open Lwt_result_syntax in + skip_list_ordering + dal + genesis_history + ~mk_level:(fun id -> Raw_level_repr.succ id.S.published_level) + ~mk_slot_index:(fun id -> id.S.index) + ~check_result:(fun res -> + let* _skip_list = Assert.get_ok ~__LOC__ res in + return_unit) + +(** This test attemps to add a slot on top of genesis cell zero which satisfies +the ordering. *) +let correct_insertion_in_skip_list_ordering_2 dal () = + let open Lwt_result_syntax in + skip_list_ordering + dal + genesis_history + ~mk_level:(fun id -> id.S.published_level) + ~mk_slot_index:(fun id -> succ_slot_index id.S.index) + ~check_result:(fun res -> + let* _skip_list = Assert.get_ok ~__LOC__ res in + return_unit) + +(** This test attemps to add two slots on top of genesis cell zero which satisfies +the ordering. *) +let correct_insertion_in_skip_list_ordering_3 dal () = + let open Lwt_result_syntax in + skip_list_ordering + dal + genesis_history + ~mk_level:(fun id -> id.S.published_level) + ~mk_slot_index:(fun id -> succ_slot_index id.S.index) + ~check_result:(fun res -> + let* skip_list = Assert.get_ok ~__LOC__ res in + skip_list_ordering + dal + skip_list + ~mk_level:(fun id -> Raw_level_repr.(succ (succ id.S.published_level))) + ~mk_slot_index:(fun id -> id.S.index) + ~check_result:(fun res -> + let* _skip_list = Assert.get_ok ~__LOC__ res in + return_unit)) + +(* Tests of construct/verify proofs that confirm/unconfirm pages on top of + genesis skip list (whose unique cell is slot zero). *) + +(** This test attemps to construct a proof to confirm a slot page from the +genesis skip list. Proof production is expected to fail. *) +let confirmed_page_on_genesis dal () = + let {S.id = {published_level; index}; _} = + Hist.Internal_for_tests.content genesis_history + in + let page_id = mk_page_id published_level index P.Index.zero in + produce_and_verify_proof + dal + genesis_history + genesis_history_cache + (* values of level and slot index are equal to slot zero. We would get a + page confirmation proof. But, no proof that confirms existance of a page + in slot [zero] is possible. *) + ~page_info:None + ~page_id + ~check_produce: + (failing_check_produce_result + ~__LOC__ + "Skip_list.search returned 'Found ': No existence proof \ + should be constructed with the slot zero.") + +(** This test attemps to construct a proof to unconfirm a slot page from the +genesis skip list. Proof production is expected to succeed. *) +let unconfirmed_page_on_genesis dal incr_level = + let {S.id = {published_level; index}; _} = + Hist.Internal_for_tests.content genesis_history + in + let level, sindex = + if incr_level then (Raw_level_repr.succ published_level, index) + else (published_level, succ_slot_index index) + in + let page_id = mk_page_id level sindex P.Index.zero in + produce_and_verify_proof + dal + genesis_history + genesis_history_cache + ~page_info:None + ~page_id + ~check_produce:(successful_check_produce_result ~__LOC__ `Unconfirmed) + ~check_verify:(successful_check_verify_result ~__LOC__ `Unconfirmed) + +(* Tests of construct/verify proofs that attempt to confirm pages on top of a + (confirmed) slot added in genesis_history skip list. *) + +(** Helper function that adds a slot a top of the genesis skip list. *) +let helper_confirmed_slot_on_genesis ~level ~mk_page_info ~check_produce + ?check_verify dal = + let open Lwt_result_syntax in + let*? _slot_data, polynomial, slot = mk_slot ~level dal in + let*? skip_list, cache = + Hist.add_confirmed_slots genesis_history genesis_history_cache [slot] + |> Environment.wrap_tzresult + in + let*? page_info, page_id = mk_page_info dal slot polynomial in + produce_and_verify_proof + dal + skip_list + cache + ~page_info + ~page_id + ?check_verify + ~check_produce + +(** Test where a slot is confirmed, requesting a proof for a confirmed page, + where the correct data and page proof are provided. *) +let confirmed_slot_on_genesis_confirmed_page_good_data dal () = + helper_confirmed_slot_on_genesis + dal + ~level:(Raw_level_repr.succ level_ten) + ~mk_page_info + ~check_produce:(successful_check_produce_result ~__LOC__ `Confirmed) + ~check_verify:(successful_check_verify_result ~__LOC__ `Confirmed) + +(** Test where a slot is confirmed, requesting a proof for a confirmed page, + where the page data and proof are not given. *) +let confirmed_slot_on_genesis_confirmed_page_no_data dal () = + helper_confirmed_slot_on_genesis + dal + ~level:(Raw_level_repr.succ level_ten) + ~mk_page_info:(mk_page_info ~custom_data:no_data) + ~check_produce: + (failing_check_produce_result + ~__LOC__ + "produce_proof needs page's info (data and proof) to construct the \ + proof, but not info are given.") + +(** Test where a slot is confirmed, requesting a proof for a confirmed page, + where correct data are provided, but the given page proof is wrong. *) +let confirmed_slot_on_genesis_confirmed_page_bad_page_proof dal () = + let open Result_syntax in + helper_confirmed_slot_on_genesis + dal + ~level:(Raw_level_repr.succ level_ten) + ~mk_page_info:(fun dal slot poly -> + let* page_info1, _page_id1 = mk_page_info ~page_index:1 dal slot poly in + let* page_info2, page_id2 = mk_page_info ~page_index:2 dal slot poly in + assert ( + match (page_info1, page_info2) with + | Some (_d1, p1), Some (_d2, p2) -> not (eq_page_proof p1 p2) + | _ -> false) ; + return (page_info1, page_id2)) + ~check_produce: + (failing_check_produce_result + ~__LOC__ + "Wrong page content for the given page index and slot comitment (page \ + data=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, \ + page id=(published_level: 11, slot_index: 0, page_index: 2), \ + commitment=sh1veuXUPvxu6SWCWtN5v2erwCQVc787gZbFT5LEbixWPLdzb8gemTzAoodnoxJ5HHU2rqu9Ph).") + +(** Test where a slot is confirmed, requesting a proof for a confirmed page, + where correct page proof is provided, but given page data are altered. *) +let confirmed_slot_on_genesis_confirmed_page_bad_data_right_length dal () = + helper_confirmed_slot_on_genesis + dal + ~level:(Raw_level_repr.succ level_ten) + ~mk_page_info: + (mk_page_info + ~custom_data: + (Some + (fun ~default_char page_size -> + Some + (Bytes.init page_size (fun i -> + if i = 0 then next_char default_char else default_char))))) + ~check_produce: + (failing_check_produce_result + ~__LOC__ + "Wrong page content for the given page index and slot comitment (page \ + data=yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, \ + page id=(published_level: 11, slot_index: 0, page_index: 0), \ + commitment=sh1veuXUPvxu6SWCWtN5v2erwCQVc787gZbFT5LEbixWPLdzb8gemTzAoodnoxJ5HHU2rqu9Ph).") + +(** Same as {!confirmed_slot_on_genesis_confirmed_page_bad_data_right_length} +but data are too short. *) +let confirmed_slot_on_genesis_confirmed_page_bad_data_short dal () = + let open Result_syntax in + helper_confirmed_slot_on_genesis + dal + ~level:(Raw_level_repr.succ level_ten) + ~mk_page_info:(fun dal slot poly -> + let custom_data = + Some + (fun ~default_char page_size -> + (* having less bytes than page size *) + Some (Bytes.make (page_size - 1) default_char)) + in + let* page_info, page_id = mk_page_info dal slot poly ~custom_data in + return (page_info, page_id)) + ~check_produce:(failing_check_produce_result ~__LOC__ "TODO") + +(** Same as {!confirmed_slot_on_genesis_confirmed_page_bad_data_right_length} +but data are too long. *) +let confirmed_slot_on_genesis_confirmed_page_bad_data_long dal () = + let open Result_syntax in + helper_confirmed_slot_on_genesis + dal + ~level:(Raw_level_repr.succ level_ten) + ~mk_page_info:(fun dal slot polynomial -> + let custom_data = + Some + (fun ~default_char page_size -> + (* having more bytes than page size *) + Some (Bytes.make (page_size + 1) default_char)) + in + let* page_info, page_id = mk_page_info dal slot polynomial ~custom_data in + return (page_info, page_id)) + ~check_produce:(failing_check_produce_result ~__LOC__ "TODO") + +(* Variants of the tests above: Construct/verify proofs that attempt to + unconfirm pages on top of a (confirmed) slot added in genesis_history skip + list. + + All the tests are somehow equivalent when building "Unconfirmed page" proof, + because the page's data & page's proof are ignored in this case. +*) + +(** Specialisation of helper {!helper_confirmed_slot_on_genesis}, where some +parameters are fixed. *) +let helper_confirmed_slot_on_genesis_unconfirmed_page ~page_level ~mk_page_info + dal = + helper_confirmed_slot_on_genesis + dal + ~level:(Raw_level_repr.succ page_level) + ~mk_page_info + ~check_produce:(successful_check_produce_result ~__LOC__ `Unconfirmed) + ~check_verify:(successful_check_verify_result ~__LOC__ `Unconfirmed) + +(** Unconfirmation proof for a page with good data. *) +let confirmed_slot_on_genesis_unconfirmed_page_good_data dal () = + helper_confirmed_slot_on_genesis_unconfirmed_page + dal + ~page_level:level_ten + ~mk_page_info:(mk_page_info ~level:level_ten) + +(** Unconfirmation proof for a page with no data. *) +let confirmed_slot_on_genesis_unconfirmed_page_no_data dal () = + helper_confirmed_slot_on_genesis_unconfirmed_page + dal + ~page_level:level_ten + ~mk_page_info:(mk_page_info ~custom_data:no_data ~level:level_ten) + +(** Unconfirmation proof for a page with bad page proof. *) +let confirmed_slot_on_genesis_unconfirmed_page_bad_proof dal () = + let open Result_syntax in + let level = level_ten in + helper_confirmed_slot_on_genesis_unconfirmed_page + dal + ~page_level:level + ~mk_page_info:(fun dal slot poly -> + let* page_info1, _page_id1 = + mk_page_info ~level:level_ten ~page_index:1 dal slot poly + in + let* _page_info2, page_id2 = + mk_page_info ~level:level_ten ~page_index:2 dal slot poly + in + assert ( + match (page_info1, _page_info2) with + | Some (_d1, p1), Some (_d2, p2) -> not (eq_page_proof p1 p2) + | _ -> false) ; + return (page_info1, page_id2)) + +(** Unconfirmation proof for a page with bad data. *) +let confirmed_slot_on_genesis_unconfirmed_page_bad_data dal () = + let level = level_ten in + helper_confirmed_slot_on_genesis_unconfirmed_page + dal + ~page_level:level + ~mk_page_info: + (mk_page_info + ~level:level_ten + ~custom_data: + (Some + (fun ~default_char page_size -> + Some + (Bytes.init page_size (fun i -> + if i = 0 then next_char default_char else default_char))))) + +(* The list of tests. *) +let tests = + Result.value_f + (dal_mk_env + { + Hist.redundancy_factor = 16; + page_size = 4096 / 64; + slot_size = 1048576 / 64; + number_of_shards = 2048 / 64; + }) + ~default:(fun () -> + Format.eprintf "failed to initialize Cryptobox.t" ; + assert false) + |> fun dal -> + let tztest title test_function = + Tztest.tztest title `Quick (test_function dal) + in + let qcheck2 name gen test = + Tztest.tztest_qcheck2 ~name ~count:1 gen (test dal) + in + let bool = QCheck2.Gen.bool in + let ordering_tests = + [ + tztest + "add a slot on top of genesis that breaks ordering" + insertion_breaks_skip_list_ordering; + tztest + "add a slot on top of genesis that satisfies ordering (1/2)" + correct_insertion_in_skip_list_ordering_1; + tztest + "add a slot on top of genesis that satisfies ordering (2/2)" + correct_insertion_in_skip_list_ordering_2; + tztest + "add two slots on top of genesis that satisfy ordering" + correct_insertion_in_skip_list_ordering_3; + ] + in + let proofs_tests_on_genesis = + [ + tztest "Confirmed page on genesis" confirmed_page_on_genesis; + qcheck2 "Unconfirmed page on genesis" bool unconfirmed_page_on_genesis; + ] + in + + let confirmed_slot_on_genesis_confirmed_page_tests = + [ + tztest + "Confirmed slot on top of genesis: confirmed page with good data" + confirmed_slot_on_genesis_confirmed_page_good_data; + tztest + "Confirmed slot on top of genesis: confirmed page with no data" + confirmed_slot_on_genesis_confirmed_page_no_data; + tztest + "Confirmed slot on top of genesis: confirmed page with bad proof" + confirmed_slot_on_genesis_confirmed_page_bad_page_proof; + tztest + "Confirmed slot on top of genesis: confirmed page with bad data " + confirmed_slot_on_genesis_confirmed_page_bad_data_right_length + (* (* TODO/DAL: https://gitlab.com/tezos/tezos/-/issues/3888 + uncomment these tests once the checks suggested in the issue above are + done. + *) + tztest + "Confirmed slot on top of genesis: confirmed page with short data " + confirmed_slot_on_genesis_confirmed_page_bad_data_short; + tztest + "Confirmed slot on top of genesis: confirmed page with long data " + confirmed_slot_on_genesis_confirmed_page_bad_data_long; + *); + ] + in + let confirmed_slot_on_genesis_unconfirmed_page_tests = + [ + tztest + "Confirmed slot on top of genesis: unconfirmed page with good data" + confirmed_slot_on_genesis_unconfirmed_page_good_data; + tztest + "Confirmed slot on top of genesis: unconfirmed page with no data" + confirmed_slot_on_genesis_unconfirmed_page_no_data; + tztest + "Confirmed slot on top of genesis: unconfirmed page with bad proof" + confirmed_slot_on_genesis_unconfirmed_page_bad_proof; + tztest + "Confirmed slot on top of genesis: unconfirmed page with bad data \ + (altered)" + confirmed_slot_on_genesis_unconfirmed_page_bad_data; + ] + in + ordering_tests @ proofs_tests_on_genesis + @ confirmed_slot_on_genesis_confirmed_page_tests + @ confirmed_slot_on_genesis_unconfirmed_page_tests -- GitLab