From 29a0014d40fa6e12da02a811d8a10d32b2d121e9 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Wed, 8 Oct 2025 17:18:49 +0200 Subject: [PATCH 1/2] DAL/Proto: store past parameters --- src/proto_alpha/lib_plugin/RPC.ml | 15 ++++ src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 1 + src/proto_alpha/lib_protocol/alpha_context.ml | 5 +- .../lib_protocol/alpha_context.mli | 7 +- .../lib_protocol/constants_parametric_repr.ml | 17 +++++ .../constants_parametric_repr.mli | 7 ++ src/proto_alpha/lib_protocol/dal_storage.ml | 72 +++++++++++++++++++ src/proto_alpha/lib_protocol/dal_storage.mli | 32 +++++++++ src/proto_alpha/lib_protocol/dune | 4 ++ src/proto_alpha/lib_protocol/init_storage.ml | 25 +++---- src/proto_alpha/lib_protocol/storage.ml | 10 +-- src/proto_alpha/lib_protocol/storage.mli | 8 ++- src/proto_alpha/lib_protocol/validate.ml | 7 +- 13 files changed, 178 insertions(+), 32 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/dal_storage.ml create mode 100644 src/proto_alpha/lib_protocol/dal_storage.mli diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index e228a632c941..4e298c1a5060 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -3072,6 +3072,13 @@ module Dal = struct ~output:(Data_encoding.list shards_assignment_encoding) RPC_path.(path / "shards") + let past_parameters = + RPC_service.get_service + ~description:"Get the DAL parameters to use for a given level" + ~output:Constants.Parametric.dal_encoding + ~query:RPC_query.empty + RPC_path.(path / "past_parameters" /: Raw_level.rpc_arg) + let published_slot_headers = let output = Data_encoding.(list Dal.Slot.Header.encoding) in RPC_service.get_service @@ -3140,6 +3147,13 @@ module Dal = struct [] |> return + let register_past_parameters () = + Registration.register1 ~chunked:false S.past_parameters + @@ fun ctxt level () () -> Dal.Past_parameters.parameters ctxt level + + let past_parameters ctxt block level = + RPC_context.make_call1 S.past_parameters ctxt block level () () + let dal_published_slot_headers ctxt block ?level () = RPC_context.make_call0 S.published_slot_headers ctxt block level () @@ -3168,6 +3182,7 @@ module Dal = struct let register () = register_dal_commitments_history () ; register_shards () ; + register_past_parameters () ; register_published_slot_headers () ; register_skip_list_cells_of_level () end diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 40f46d10c7de..3a98a5337a15 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -213,6 +213,7 @@ "Sc_rollup_storage", "Sc_rollup_stake_storage", "Dal_slot_storage", + "Dal_storage", "Sc_rollup_refutation_storage", "Zk_rollup_errors", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 81aa581aa3cf..61440488ed1d 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -169,10 +169,7 @@ module Dal = struct module Slots_history = Dal_slot_repr.History module Slots_storage = Dal_slot_storage module Delegate = Dal_already_denounced_storage - - module Prev_attestation_lag = struct - let get = Storage.Dal.Prev_attestation_lag.get - end + module Past_parameters = Dal_storage end module Dal_errors = Dal_errors_repr diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 88f4cde6ab03..e9e1a217dfb4 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -861,6 +861,8 @@ module Constants : sig traps_fraction : Q.t; } + val dal_encoding : dal Data_encoding.t + type sc_rollup_reveal_hashing_schemes = {blake2B : Raw_level.t} type sc_rollup_reveal_activation_level = { @@ -3204,8 +3206,9 @@ module Dal : sig val is_denounced : context -> public_key_hash -> bool Lwt.t end - module Prev_attestation_lag : sig - val get : context -> int tzresult Lwt.t + module Past_parameters : sig + val parameters : + context -> Raw_level.t -> Constants.Parametric.dal tzresult Lwt.t end end diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml index 4ee710afe937..4f7a2ac461f2 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml @@ -57,6 +57,12 @@ type dal = { traps_fraction : Q.t; } +type past_dal_parameters = { + dal_parameters : dal; + next_protocol_activation : Raw_level_repr.t; + (** This is the migration level up to which the parameters were used. *) +} + let minimal_participation_ratio_encoding = between_zero_and_one_q_encoding "dal.minimal_participation_ratio must be a value between zero and one" @@ -129,6 +135,17 @@ let dal_encoding = (req "traps_fraction" traps_fraction_encoding)) Dal.parameters_encoding) +let past_dal_parameters_encoding = + let open Data_encoding in + conv + (fun {dal_parameters; next_protocol_activation} -> + (dal_parameters, next_protocol_activation)) + (fun (dal_parameters, next_protocol_activation) -> + {dal_parameters; next_protocol_activation}) + (obj2 + (req "dal_parameters" dal_encoding) + (req "next_protocol_activation" Raw_level_repr.encoding)) + (* The encoded representation of this type is stored in the context as bytes. Changing the encoding, or the value of these constants from the previous protocol may break the context migration, or (even diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli index 152721db2884..3b7dee73aa31 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli @@ -84,8 +84,15 @@ type dal = { traps_fraction : Q.t; (* probability that a given shard is a trap *) } +type past_dal_parameters = { + dal_parameters : dal; + next_protocol_activation : Raw_level_repr.t; +} + val dal_encoding : dal Data_encoding.t +val past_dal_parameters_encoding : past_dal_parameters Data_encoding.t + type sc_rollup_reveal_hashing_schemes = {blake2B : Raw_level_repr.t} (** Associates reveal kinds to their activation level. *) diff --git a/src/proto_alpha/lib_protocol/dal_storage.ml b/src/proto_alpha/lib_protocol/dal_storage.ml new file mode 100644 index 000000000000..184c51e70262 --- /dev/null +++ b/src/proto_alpha/lib_protocol/dal_storage.ml @@ -0,0 +1,72 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2025 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +module Store = Storage.Dal + +let get_past_parameters ctxt = + let open Lwt_result_syntax in + let+ cell = Store.Past_parameters.find ctxt in + Option.value ~default:[] cell + +let save_parameters ctxt + (previous_parameters : Constants_parametric_previous_repr.dal) + ~next_protocol_activation = + let open Lwt_result_syntax in + let* past_parameters = get_past_parameters ctxt in + let previous_parameters : Constants_parametric_repr.dal = + let Constants_parametric_previous_repr. + { + feature_enable; + incentives_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + cryptobox_parameters; + minimal_participation_ratio; + rewards_ratio; + traps_fraction; + } = + previous_parameters + in + { + feature_enable; + incentives_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + cryptobox_parameters; + minimal_participation_ratio; + rewards_ratio; + traps_fraction; + } + in + let*! ctxt = + Store.Past_parameters.add + ctxt + (Constants_parametric_repr. + {dal_parameters = previous_parameters; next_protocol_activation} + :: past_parameters) + in + return ctxt + +let parameters ctxt level = + let open Lwt_result_syntax in + let* past_parameters = get_past_parameters ctxt in + let parameters = + List.find_map + (fun Constants_parametric_repr.{dal_parameters; next_protocol_activation} + -> + if Raw_level_repr.(level <= next_protocol_activation) then + Some dal_parameters + else None) + (List.rev past_parameters) + in + match parameters with + | Some parameters -> return parameters + | None -> + let constants = Constants_storage.parametric ctxt in + return constants.dal diff --git a/src/proto_alpha/lib_protocol/dal_storage.mli b/src/proto_alpha/lib_protocol/dal_storage.mli new file mode 100644 index 000000000000..e5841d268565 --- /dev/null +++ b/src/proto_alpha/lib_protocol/dal_storage.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2025 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** [save_parameters ctxt constants_previous ~next_protocol_activation] is called + when a new protocol is activated, that is at the end of the last block of its + previous protocol. Therefore [next_protocol_activation] is the level of the + last block of the previous protocol, alongside the protocol constants used + for this protocol: [constant_previous]. + + The activation level and the parameters are saved in the context. Note that + it transforms {!Constants_parametric_previous_repr.dal} to + {!Constants_parametric_repr.dal}, therefore it assumes that it can be + transformed at migration time. If for a given protocol it's not possible, + retrocompatible encoding needs to be introduced. *) +val save_parameters : + Raw_context.t -> + Constants_parametric_previous_repr.dal -> + next_protocol_activation:Raw_level_repr.t -> + Raw_context.t tzresult Lwt.t + +(** [parameters ctxt level] returns the constants used for a given [level]. When + [level] is a migration level, it returns the constants of the protocol that + ends at that level. If the level is greater than any protocol migration + level, it returns the current protocol constants. *) +val parameters : + Raw_context.t -> + Raw_level_repr.t -> + Constants_parametric_repr.dal tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index 7fea31a9fe26..d0771299a264 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -225,6 +225,7 @@ Sc_rollup_storage Sc_rollup_stake_storage Dal_slot_storage + Dal_storage Sc_rollup_refutation_storage Zk_rollup_errors Address_registry_storage @@ -523,6 +524,7 @@ sc_rollup_storage.ml sc_rollup_storage.mli sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli dal_slot_storage.ml dal_slot_storage.mli + dal_storage.ml dal_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli zk_rollup_errors.ml address_registry_storage.ml address_registry_storage.mli @@ -822,6 +824,7 @@ sc_rollup_storage.ml sc_rollup_storage.mli sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli dal_slot_storage.ml dal_slot_storage.mli + dal_storage.ml dal_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli zk_rollup_errors.ml address_registry_storage.ml address_registry_storage.mli @@ -1105,6 +1108,7 @@ sc_rollup_storage.ml sc_rollup_storage.mli sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli dal_slot_storage.ml dal_slot_storage.mli + dal_storage.ml dal_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli zk_rollup_errors.ml address_registry_storage.ml address_registry_storage.mli diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index 288367f02460..c91ce93c1703 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -142,10 +142,16 @@ let prepare_first_block chain_id ctxt ~typecheck_smart_contract let* ctxt = match previous_proto_constants with | Some previous_proto_constants -> - Sc_rollup_storage.save_commitment_period + let* ctxt = + Sc_rollup_storage.save_commitment_period + ctxt + previous_proto_constants.sc_rollup.commitment_period_in_blocks + level + in + Dal_storage.save_parameters ctxt - previous_proto_constants.sc_rollup.commitment_period_in_blocks - level + previous_proto_constants.dal + ~next_protocol_activation:level | None -> return ctxt in let parametric = Raw_context.constants ctxt in @@ -238,19 +244,6 @@ let prepare_first_block chain_id ctxt ~typecheck_smart_contract let* ctxt = Sc_rollup_refutation_storage.migrate_clean_refutation_games ctxt in - let* ctxt = - match previous_proto_constants with - | Some previous_proto_constants -> - let*! ctxt = - Storage.Dal.Prev_attestation_lag.add - ctxt - previous_proto_constants.dal.attestation_lag - in - return ctxt - | None -> - (* unreachable because the previous protocol is not Genesis *) - assert false - in return (ctxt, []) (* End of alpha predecessor stitching. Comment used for automatic snapshot *) in diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 0850624c0268..85d55c91d8e3 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -2380,15 +2380,17 @@ module Dal = struct let encoding = Data_encoding.empty end) - module Prev_attestation_lag = + module Past_parameters = Make_single_data_storage (Registered) (Raw_context) (struct - let name = ["dal_prev_attestation_lag"] + let name = ["past_parameters"] end) (struct - type t = int + type t = Constants_parametric_repr.past_dal_parameters list - let encoding = Data_encoding.uint8 + let encoding = + Data_encoding.list + Constants_parametric_repr.past_dal_parameters_encoding end) end diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index d37fbd9241de..e06cdfd9290a 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -1130,10 +1130,12 @@ module Dal : sig and type key = Signature.Public_key_hash.t and type value = unit - (** This stores the value of [attestation_lag] at the previous protocol. + (** This stores the value of Dal constants for each protocol. Useful during protocol migration when the parameter's value changes. *) - module Prev_attestation_lag : - Single_data_storage with type t := Raw_context.t and type value = int + module Past_parameters : + Single_data_storage + with type value = Constants_parametric_repr.past_dal_parameters list + and type t := Raw_context.t end module Zk_rollup : sig diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 610d4140a3bf..a2238b2029d1 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -2504,9 +2504,10 @@ module Anonymous = struct in let* attestation_lag = let* migration_level = First_level_of_protocol.get ctxt in - if Raw_level.(level.level < migration_level) then - Alpha_context.Dal.Prev_attestation_lag.get ctxt - else return (Constants.parametric vi.ctxt).dal.attestation_lag + let+ parameters = + Alpha_context.Dal.Past_parameters.parameters ctxt migration_level + in + parameters.attestation_lag in let* published_level = match Raw_level.(sub (succ level.level) attestation_lag) with -- GitLab From 5f89822860b9876d3a93fc6d87b3599666ef2566 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Fri, 17 Oct 2025 16:40:43 +0200 Subject: [PATCH 2/2] DAL/Test: test past_parameters storage --- manifest/product_octez.ml | 2 + src/proto_alpha/lib_protocol/test/unit/dune | 1 + .../unit/test_dal_past_parameters_storage.ml | 160 ++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 src/proto_alpha/lib_protocol/test/unit/test_dal_past_parameters_storage.ml diff --git a/manifest/product_octez.ml b/manifest/product_octez.ml index 4078d1ecdab0..860ab0733155 100644 --- a/manifest/product_octez.ml +++ b/manifest/product_octez.ml @@ -6552,6 +6552,8 @@ end = struct ("test_sc_rollup_wasm", N.(number >= 016)); ("test_local_contexts", N.(number >= 016)); ("test_dal_slot_proof", N.(number >= 016)); + ( "test_dal_past_parameters_storage", + N.(number >= 025 && name_dash <> "024-PsD5wVTJ") ); ("test_adaptive_issuance", N.(number >= 018)); ("test_adaptive_issuance_ema", N.(number <= 023)); ("test_percentage", N.(number >= 019)); diff --git a/src/proto_alpha/lib_protocol/test/unit/dune b/src/proto_alpha/lib_protocol/test/unit/dune index 51d1bcfd02da..8c6abe868656 100644 --- a/src/proto_alpha/lib_protocol/test/unit/dune +++ b/src/proto_alpha/lib_protocol/test/unit/dune @@ -71,6 +71,7 @@ test_sc_rollup_wasm test_local_contexts test_dal_slot_proof + test_dal_past_parameters_storage test_adaptive_issuance test_percentage test_full_staking_balance_repr diff --git a/src/proto_alpha/lib_protocol/test/unit/test_dal_past_parameters_storage.ml b/src/proto_alpha/lib_protocol/test/unit/test_dal_past_parameters_storage.ml new file mode 100644 index 000000000000..7f5faaf7af23 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/unit/test_dal_past_parameters_storage.ml @@ -0,0 +1,160 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2025 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (dal past parameters storage) + Invocation: dune exec src/proto_alpha/lib_protocol/test/unit/main.exe \ + -- --file test_dal_past_parameters_storage.ml + Subject: These unit tests check Dal past parameter storage functions. +*) + +open Protocol + +let assert_equal_parameters ~__LOC__ = + let open Constants_parametric_repr in + let eq x y = x.attestation_lag = y.attestation_lag in + Assert.equal ~loc:__LOC__ eq "parameters.attestation_lag" (fun fmt x -> + Format.pp_print_int fmt x.attestation_lag) + +let parameters_for_a_level () = + let open Lwt_result_wrap_syntax in + let* b, _contracts = Context.init1 () in + let* inc = Incremental.begin_construction b in + let ctxt = Incremental.alpha_ctxt inc in + + let ctxt = Alpha_context.Internal_for_tests.to_raw ctxt in + + let parameters n = + Constants_parametric_previous_repr. + { + feature_enable = true; + incentives_enable = true; + number_of_slots = 1; + attestation_lag = n; + attestation_threshold = 1; + cryptobox_parameters = + Cryptobox. + { + redundancy_factor = 1; + page_size = 1; + slot_size = 1; + number_of_shards = 1; + }; + minimal_participation_ratio = Q.zero; + rewards_ratio = Q.zero; + traps_fraction = Q.zero; + } + in + let previous_parameters_to_current previous_parameters = + let Constants_parametric_previous_repr. + { + feature_enable; + incentives_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + cryptobox_parameters; + minimal_participation_ratio; + rewards_ratio; + traps_fraction; + } = + previous_parameters + in + Constants_parametric_repr. + { + feature_enable; + incentives_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + cryptobox_parameters; + minimal_participation_ratio; + rewards_ratio; + traps_fraction; + } + in + let*@ ctxt = + Dal_storage.save_parameters + ctxt + (parameters 5) + ~next_protocol_activation:(Raw_level_repr.of_int32_exn 5l) + in + let*@ ctxt = + Dal_storage.save_parameters + ctxt + (parameters 10) + ~next_protocol_activation:(Raw_level_repr.of_int32_exn 10l) + in + let*@ ctxt = + Dal_storage.save_parameters + ctxt + (parameters 15) + ~next_protocol_activation:(Raw_level_repr.of_int32_exn 15l) + in + + let*@ stored_parameters = + Dal_storage.parameters ctxt (Raw_level_repr.of_int32_exn 0l) + in + let* () = + assert_equal_parameters + ~__LOC__ + stored_parameters + (previous_parameters_to_current @@ parameters 5) + in + + let*@ stored_parameters = + Dal_storage.parameters ctxt (Raw_level_repr.of_int32_exn 5l) + in + let* () = + assert_equal_parameters + ~__LOC__ + stored_parameters + (previous_parameters_to_current @@ parameters 5) + in + + let*@ stored_parameters = + Dal_storage.parameters ctxt (Raw_level_repr.of_int32_exn 10l) + in + let* () = + assert_equal_parameters + ~__LOC__ + stored_parameters + (previous_parameters_to_current @@ parameters 10) + in + + let*@ stored_parameters = + Dal_storage.parameters ctxt (Raw_level_repr.of_int32_exn 15l) + in + let* () = + assert_equal_parameters + ~__LOC__ + stored_parameters + (previous_parameters_to_current @@ parameters 15) + in + + (* If the level is greater than any saved parameters, whatever are the current + protocol constants are returned. *) + let*@ stored_parameters = + Dal_storage.parameters ctxt (Raw_level_repr.of_int32_exn 20l) + in + let current_constants = Raw_context.constants ctxt in + let* () = + assert_equal_parameters ~__LOC__ stored_parameters current_constants.dal + in + + return_unit + +let tests = + [Tztest.tztest "parameters for a level" `Quick parameters_for_a_level] + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [("dal past parameters storage", tests)] + |> Lwt_main.run -- GitLab