From 0f66a4a6357af1502c545cd61d4e4218c26f20e0 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 16 Sep 2025 10:21:38 +0200 Subject: [PATCH 01/34] Proto/tests: init context with initer --- .../lib_protocol/test/helpers/block.ml | 17 ++++++++++++++++- .../lib_protocol/test/helpers/block.mli | 6 +++++- .../lib_protocol/test/helpers/context.ml | 19 +++++++++++-------- .../lib_protocol/test/helpers/context.mli | 7 +++++++ 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index eab4841715cc..19f270b174a3 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -526,7 +526,7 @@ let initial_alpha_context ?(commitments = []) constants in return result -let genesis_with_parameters parameters = +let genesis_with_parameters ?prepare_context parameters = let open Lwt_result_wrap_syntax in let hash = Block_hash.of_b58check_exn @@ -567,6 +567,21 @@ let genesis_with_parameters parameters = in let chain_id = Chain_id.of_block_hash hash in let*@ {context; _} = Main.init chain_id ctxt shell in + let* context = + match prepare_context with + | None -> return context + | Some f -> + let*@ context, _balance_updates, _origination_results = + Init_storage.prepare + context + ~level:0l + ~predecessor_timestamp:Time.Protocol.epoch + ~timestamp:Time.Protocol.epoch + in + let*@ context = f context in + let context = Raw_context.recover context in + return context + in return { hash; diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.mli b/src/proto_alpha/lib_protocol/test/helpers/block.mli index 237819d40f60..ba3cebb0aa02 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/block.mli @@ -163,7 +163,11 @@ val genesis : Parameters.bootstrap_account list -> block tzresult Lwt.t -val genesis_with_parameters : Parameters.t -> block tzresult Lwt.t +val genesis_with_parameters : + ?prepare_context: + (Raw_context.t -> Raw_context.t Environment.Error_monad.tzresult Lwt.t) -> + Parameters.t -> + block tzresult Lwt.t (** [alpha_context accounts] : instantiates an alpha_context with the given constants [] and initializes [accounts] with their diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.ml b/src/proto_alpha/lib_protocol/test/helpers/context.ml index 898769a67d8e..93955bcbfc3a 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/context.ml @@ -31,6 +31,9 @@ open Plugin type t = B of Block.t | I of Incremental.t +type raw_context_modifier = + Raw_context.t -> Raw_context.t Environment.Error_monad.tzresult Lwt.t + (* Begins the construction of a block with the first available baker. Fails if no baker can bake the next block. *) let get_alpha_ctxt c = @@ -837,7 +840,7 @@ let create_bootstrap_accounts_algo_list algo_list = let bootstrap_accounts = Account.make_bootstrap_accounts accounts in (bootstrap_accounts, contracts) -let init_with_constants_gen ?algo tup constants = +let init_with_constants_gen ?algo ?prepare_context tup constants = let open Lwt_result_syntax in let n = tup_n tup in let*? bootstrap_accounts, contracts = create_bootstrap_accounts ?algo n in @@ -846,13 +849,13 @@ let init_with_constants_gen ?algo tup constants = ~bootstrap_accounts constants in - let* blk = Block.genesis_with_parameters parameters in + let* blk = Block.genesis_with_parameters ?prepare_context parameters in return (blk, tup_get tup contracts) -let init_with_constants_n ?algo constants n = - init_with_constants_gen ?algo (TList n) constants +let init_with_constants_n ?algo ?prepare_context constants n = + init_with_constants_gen ?algo ?prepare_context (TList n) constants -let init_with_constants_algo_list constants algo_list = +let init_with_constants_algo_list ?prepare_context constants algo_list = let open Lwt_result_syntax in let n = List.length algo_list in let tup = TList n in @@ -864,19 +867,19 @@ let init_with_constants_algo_list constants algo_list = ~bootstrap_accounts constants in - let* blk = Block.genesis_with_parameters parameters in + let* blk = Block.genesis_with_parameters ?prepare_context parameters in return (blk, tup_get tup contracts) let init_with_constants1 = init_with_constants_gen T1 let init_with_constants2 = init_with_constants_gen T2 -let init_with_parameters_gen tup parameters = +let init_with_parameters_gen ?prepare_context tup parameters = let open Lwt_result_syntax in let n = tup_n tup in let*? bootstrap_accounts, contracts = create_bootstrap_accounts n in let parameters = Parameters.{parameters with bootstrap_accounts} in - let* blk = Block.genesis_with_parameters parameters in + let* blk = Block.genesis_with_parameters ?prepare_context parameters in return (blk, tup_get tup contracts) let init_with_parameters_n params n = init_with_parameters_gen (TList n) params diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.mli b/src/proto_alpha/lib_protocol/test/helpers/context.mli index 7d9677cf8d1d..1453b2dec113 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/context.mli @@ -30,6 +30,9 @@ open Alpha_context type t = B of Block.t | I of Incremental.t +type raw_context_modifier = + Raw_context.t -> Raw_context.t Environment.Error_monad.tzresult Lwt.t + val get_alpha_ctxt : t -> context tzresult Lwt.t val branch : t -> Block_hash.t @@ -454,17 +457,20 @@ val init3 : val init_with_constants_gen : ?algo:Signature.algo -> + ?prepare_context:raw_context_modifier -> (Alpha_context.Contract.t, 'contracts) tup -> Constants.Parametric.t -> (Block.t * 'contracts) tzresult Lwt.t val init_with_constants_n : ?algo:Signature.algo -> + ?prepare_context:raw_context_modifier -> Constants.Parametric.t -> int -> (Block.t * Alpha_context.Contract.t list) tzresult Lwt.t val init_with_constants_algo_list : + ?prepare_context:raw_context_modifier -> Constants.Parametric.t -> Signature.algo option list -> (Block.t * Alpha_context.Contract.t list) tzresult Lwt.t @@ -482,6 +488,7 @@ val init_with_constants2 : accounts. The number of bootstrap accounts, and the structure of the returned contracts, are specified by the [tup] argument. *) val init_with_parameters_gen : + ?prepare_context:raw_context_modifier -> (Alpha_context.Contract.t, 'contracts) tup -> Parameters.t -> (Block.t * 'contracts) tzresult Lwt.t -- GitLab From 02ca1ad4e8297bb3e65c8e7e5131e49e2448f704 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 16 Sep 2025 16:32:18 +0200 Subject: [PATCH 02/34] Proto/tests: can init with cks for bootstraps begin_test syntaxt chnaged a bit, should be more flexible and allow for more changes in the future (bootstrap initial funds for instance) without changing current behavior or syntax for existing tests --- .../test/helpers/account_helpers.ml | 15 +- .../test/helpers/scenario_begin.ml | 219 ++++++++++++++++-- .../consensus/test_companion_key.ml | 22 +- .../consensus/test_scenario_attestation.ml | 28 ++- .../integration/test_scenario_slashing.ml | 4 +- 5 files changed, 246 insertions(+), 42 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/account_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/account_helpers.ml index b41470f1225c..876ada3befb8 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/account_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/account_helpers.ml @@ -70,7 +70,8 @@ let init_account ~name ?delegate ~pkh ~contract ~parameters ?(liquid = Tez.zero) ?(unstaked_finalizable = Unstaked_finalizable.zero) ?(staking_delegator_numerator = Z.zero) ?(staking_delegate_denominator = Z.zero) ?(frozen_rights = CycleMap.empty) - ?(slashed_cycles = []) ?last_seen_activity () = + ?(slashed_cycles = []) ?last_seen_activity ?consensus_key ?companion_key () + = let frozen_deposits = Option.value frozen_deposits ~default:(Frozen_tez.init Tez.zero name name) in @@ -90,8 +91,16 @@ let init_account ~name ?delegate ~pkh ~contract ~parameters ?(liquid = Tez.zero) frozen_rights; slashed_cycles; last_seen_activity; - consensus_keys = CycleMap.empty; - companion_keys = CycleMap.empty; + consensus_keys = + Option.fold + ~none:CycleMap.empty + ~some:(CycleMap.singleton Cycle.root) + consensus_key; + companion_keys = + Option.fold + ~none:CycleMap.empty + ~some:(CycleMap.singleton Cycle.root) + companion_key; } type account_map = account_state String.Map.t diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml index 2b6a9ef33b9f..9073f9d649aa 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml @@ -85,24 +85,99 @@ let init_constants ?(default = Test) ?(reward_per_block = 0L) (Protocol.Issuance_bonus_repr.max_bonus_parameter_of_Q_exn Q.zero) else Empty +type algo = Any_algo | Ed25519 | Secp256k1 | P256 | Bls + +let algo_to_algo = function + | Ed25519 -> Some Signature.Ed25519 + | Secp256k1 -> Some Secp256k1 + | P256 -> Some P256 + | Bls -> Some Bls + | Any_algo -> None + +(* None = not set, Some None = set to None (not the same) *) +(* type before applying defaults *) +type bootstrap_info = { + name : string; + algo_opt : algo option; + consensus_key_algo_opt_opt : algo option option; + companion_key_flag_opt : bool option; +} + +(** Used to build bootstrap detailed info. + @param algo defines the algorithm to use for the given bootstrap. + Set to [Any_algo] to choose one randomly. + @param consensus_key [None] means that the bootstrap account does not have a consensus key. + [Some algo] will set a consensus key with the given algo. + @param companion_key is a flag that sets a BLS companion key iff the parameter is set to [true]. +*) +let make ?algo ?consensus_key ?companion_key name = + { + name; + algo_opt = algo; + consensus_key_algo_opt_opt = consensus_key; + companion_key_flag_opt = companion_key; + } + +(* type after applying defaults *) +type bootstrap_full_info = { + name : string; + algo : algo; + consensus_key_algo_opt : algo option; + companion_key_flag : bool; +} + +(* type after creating accounts *) +type bootstrap_accounts = { + name : string; + delegate : Account.t; + consensus_key : Account.t option; + companion_key : Account.t option; +} + (** Initialize the test, given some initial parameters. [algo] defines the algorithm used for the [delegates_name_list]. If not set, a random algorithm is selected for each. To use a different algorithm for each delegate, use [delegates_with_algo] *) -let begin_test ?(delegates_with_algo = []) ?algo ?(burn_rewards = false) +let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) + ?(default_algo = (Any_algo : algo)) + ?(default_consensus_key = (None : algo option)) + ?(default_companion_key = false) ?(burn_rewards = false) ?(force_attest_all = false) ?(force_preattest_all = false) ?(check_finalized_every_block = []) ?(disable_default_checks = false) - delegates_name_list : (constants, t) scenarios = + ?(rng_state = Random.State.make_self_init ()) + (default_bootstrap_name_list : string list) : (constants, t) scenarios = exec (fun (constants : constants) -> let open Lwt_result_syntax in - let delegates_name_algo = - List.map (fun x -> (x, algo)) delegates_name_list - @ List.map (fun (x, algo) -> (x, Some algo)) delegates_with_algo + let make_bootstrap_full (bootstrap_info : bootstrap_info) : + bootstrap_full_info = + { + name = bootstrap_info.name; + algo = Option.value ~default:default_algo bootstrap_info.algo_opt; + consensus_key_algo_opt = + Option.value + ~default:default_consensus_key + bootstrap_info.consensus_key_algo_opt_opt; + companion_key_flag = + Option.value + ~default:default_companion_key + bootstrap_info.companion_key_flag_opt; + } + in + let default_bootstrap name = + make_bootstrap_full + { + name; + algo_opt = None; + consensus_key_algo_opt_opt = None; + companion_key_flag_opt = None; + } in - assert (not @@ List.is_empty delegates_name_algo) ; - let delegates_name_list, delegates_algo_list = - List.split delegates_name_algo + let bootstrap_info_list = + List.map default_bootstrap default_bootstrap_name_list + @ List.map make_bootstrap_full bootstrap_info_list in + (* Please setup at least one bootstrap account *) + assert (not @@ List.is_empty bootstrap_info_list) ; (* Do not disable default checks, unless for a good reason *) let check_finalized_every_block = if disable_default_checks then check_finalized_every_block @@ -110,15 +185,112 @@ let begin_test ?(delegates_with_algo = []) ?algo ?(burn_rewards = false) [check_all_balances; check_misc; check_issuance_rpc] @ check_finalized_every_block in - (* Override threshold value if activate *) - let* block, delegates = - Context.init_with_constants_algo_list constants delegates_algo_list + (* Setup bootstraps and their keys *) + let bootstrap_accounts_list = + List.map + (fun x -> + let delegate = + Account.new_account ?algo:(algo_to_algo x.algo) ~rng_state () + in + let consensus_key = + Option.map + (fun algo -> + Account.new_account ?algo:(algo_to_algo algo) ~rng_state ()) + x.consensus_key_algo_opt + in + let companion_key = + if not x.companion_key_flag then None + else Some (Account.new_account ~algo:Bls ~rng_state ()) + in + {name = x.name; delegate; consensus_key; companion_key}) + bootstrap_info_list + in + (* Setup the bootstrap accounts in the parameters *) + let bootstrap_accounts = + List.map (fun a -> a.delegate) bootstrap_accounts_list + in + let bootstrap_consensus_keys = + List.map + (fun a -> Option.map (fun x -> x.Account.pk) a.consensus_key) + bootstrap_accounts_list + in + let bootstrap_accounts = + Account.make_bootstrap_accounts + ~bootstrap_consensus_keys + bootstrap_accounts + in + let parameters = + Tezos_protocol_alpha_parameters.Default_parameters + .parameters_of_constants + ~bootstrap_accounts + constants + in + (* Hack-in the companion keys in the context *) + let set_companion ctxt = + List.fold_left_es + (fun ctxt bootstrap -> + match bootstrap.companion_key with + | None -> return ctxt + | Some ck -> + let key = bootstrap.delegate.Account.pkh in + (* Add the companion key to the global cks storage *) + let*! ctxt = Protocol.Storage.Consensus_keys.add ctxt ck.pkh in + (* Set the companion key for the bootstrap *) + let ck_pk = match ck.pk with Bls x -> x | _ -> assert false in + let ck_pkh = + match ck.pkh with Bls x -> x | _ -> assert false + in + let*! ctxt = + Protocol.Storage.Contract.Companion_key.add + ctxt + (Implicit key) + ck_pk + in + (* Clear the cache: we need to update it with the companion key values. *) + let ctxt = Protocol.Raw_context.Cache.clear ctxt in + (* Update the [Delegate_sampler_state] with the companion key *) + let*! ctxt = + Protocol.Storage.Delegate_sampler_state.fold + ctxt + ~order:`Undefined + ~init:ctxt + ~f:(fun cycle sampler ctxt -> + let sampler = + Protocol.Sampler.map + (fun (x : Protocol.Raw_context.consensus_pk) -> + if Signature.Public_key_hash.equal x.delegate key + then + { + x with + companion_pk = Some ck_pk; + companion_pkh = Some ck_pkh; + } + else x) + sampler + in + Protocol.Storage.Delegate_sampler_state.add + ctxt + cycle + sampler) + in + return ctxt) + ctxt + bootstrap_accounts_list + in + (* Genesis *) + let* block = + Block.genesis_with_parameters ~prepare_context:set_companion parameters in let*? init_level = Context.get_level (B block) in - let*? account_map = - List.fold_left2 - ~when_different_lengths:[Inconsistent_number_of_bootstrap_accounts] - (fun account_map name contract -> + (* init state *) + let account_map = + List.fold_left + (fun account_map bootstrap_account -> + let name = bootstrap_account.name in + let contract = + Protocol.Alpha_context.Contract.Implicit + bootstrap_account.delegate.pkh + in let liquid = Account.default_initial_spendable_balance in let init_staked = Account.default_initial_staked_balance in let frozen_deposits = Frozen_tez.init init_staked name name in @@ -129,6 +301,18 @@ let begin_test ?(delegates_with_algo = []) ?algo ?(burn_rewards = false) Cycle.(root ---> add root constants.consensus_rights_delay) in let pkh = Context.Contract.pkh contract in + let consensus_key = + Option.map + (fun x -> x.Account.pkh) + bootstrap_account.consensus_key + in + let companion_key = + Option.map + (fun x -> + x.Account.pkh |> function Bls x -> x | _ -> assert false + (* by construction, the companion keys built previously are BLS *)) + bootstrap_account.companion_key + in let account = init_account ~name @@ -142,6 +326,8 @@ let begin_test ?(delegates_with_algo = []) ?algo ?(burn_rewards = false) ~frozen_rights ~last_seen_activity: Cycle.(add root constants.consensus_rights_delay) + ?consensus_key + ?companion_key () in let account_map = String.Map.add name account account_map in @@ -152,8 +338,7 @@ let begin_test ?(delegates_with_algo = []) ?algo ?(burn_rewards = false) Log.debug "Initial total balance: %a" Tez.pp total_balance ; account_map) String.Map.empty - delegates_name_list - delegates + bootstrap_accounts_list in let* total_supply = Context.get_total_supply (B block) in let state = diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml index 4407f17fe1dd..436ce42cafc9 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml @@ -228,7 +228,7 @@ let test_simple_register_consensus_and_companion_keys = --> begin_test ~force_attest_all:true ~check_finalized_every_block - ~algo:Bls + ~default_algo:Bls bootstrap_accounts --> add_account_with_funds delegate @@ -329,7 +329,7 @@ let test_register_other_accounts_as_ck = --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~algo:Bls + ~default_algo:Bls ~check_finalized_every_block:[(fun _ -> check_all_cks)] ~force_attest_all:true ["delegate"; "victim_1"; "victim_2"] @@ -392,7 +392,7 @@ let test_self_register_as_companion = --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -596,7 +596,7 @@ let test_register_same_key_multiple_times = --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -630,7 +630,7 @@ let test_register_new_key_every_cycle = --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -646,7 +646,7 @@ let test_register_key_end_of_cycle = --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -671,7 +671,7 @@ let test_registration_override = init_constants () --> set S.allow_tz4_delegate_enable true --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -771,7 +771,7 @@ let test_in_registration_table_twice = --> set S.cache_stake_distribution_cycles (consensus_rights_delay + 3) --> set S.cache_sampler_state_cycles (consensus_rights_delay + 3) --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -932,7 +932,7 @@ let test_fail_already_registered = let delegate = "delegate" in init_constants () --> set S.allow_tz4_delegate_enable true - --> begin_test ~force_attest_all:true ~algo:Bls [delegate; "ck"] + --> begin_test ~force_attest_all:true ~default_algo:Bls [delegate; "ck"] --> fold_tag (fun kind -> assert_failure @@ -977,7 +977,7 @@ let test_fail_wrong_signer = let delegate = "delegate" in init_constants () --> set S.allow_tz4_delegate_enable true - --> begin_test ~force_attest_all:true ~algo:Bls [delegate; "signer"] + --> begin_test ~force_attest_all:true ~default_algo:Bls [delegate; "signer"] --> add_account ~algo:Bls "ck" --> fold_tag (fun kind -> @@ -1000,7 +1000,7 @@ let test_fail_companion_not_tz4 = let delegate = "delegate" in init_constants () --> set S.allow_tz4_delegate_enable true - --> begin_test ~force_attest_all:true ~algo:Bls [delegate; "signer"] + --> begin_test ~force_attest_all:true ~default_algo:Bls [delegate; "signer"] --> fold_tag (fun algo -> add_account ~algo "ck") [("Ed25519", Ed25519); ("Secp256k1", Secp256k1); ("P256", P256)] diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_scenario_attestation.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_scenario_attestation.ml index 3040e90d6863..2f17886f42a2 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_scenario_attestation.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_scenario_attestation.ml @@ -153,7 +153,10 @@ let test_preattest_all = let test_attest_aggreg = init_constants () - --> begin_test ["delegate1"; "delegate2"] ~algo:Bls ~force_attest_all:false + --> begin_test + ["delegate1"; "delegate2"] + ~default_algo:Bls + ~force_attest_all:false --> next_block --> attest_aggreg_with ["delegate1"; "delegate2"] --> next_block @@ -165,7 +168,10 @@ let test_attest_aggreg = let test_preattest_aggreg = init_constants () - --> begin_test ["delegate1"; "delegate2"] ~algo:Bls ~force_preattest_all:false + --> begin_test + ["delegate1"; "delegate2"] + ~default_algo:Bls + ~force_preattest_all:false --> set_baked_round 1 --> next_block --> finalize_payload ~payload_round:0 () --> preattest_aggreg_with ["delegate1"; "delegate2"] @@ -203,13 +209,13 @@ let test_attestation_rewards = |+ Tag "tz4 (solo)" --> begin_test ["delegate"] - ~algo:Bls + ~default_algo:Bls ~disable_default_checks:true ~force_attest_all:true |+ Tag "tz4 (with others)" --> begin_test ["delegate"; "bozo1"; "bozo2"] - ~algo:Bls + ~default_algo:Bls ~disable_default_checks:true ~force_attest_all:true) --> dawn_of_next_cycle @@ -234,7 +240,7 @@ let test_missed_attestations_rewards_tz4 = (* Default checks are disabled because rewards have been changed *) --> begin_test ["delegate"; "bozo1"; "bozo2"] - ~algo:Bls + ~default_algo:Bls ~disable_default_checks:true --> snapshot_balances "init" ["delegate"] --> next_block @@ -285,7 +291,7 @@ let test_forbidden_delegate_tries_to_attest_but_fails_miserably_tz4_edition = init_constants () --> begin_test ["delegate"; "baker"; "attester"] - ~algo:Bls + ~default_algo:Bls ~force_preattest_all:false ~force_attest_all:false --> set_baker ~min_round:1 "baker" @@ -318,13 +324,13 @@ let test_attestations_keep_activation_status = --> (Tag "tz4, attest" --> begin_test accounts - ~algo:Bls + ~default_algo:Bls ~force_preattest_all:false ~force_attest_all:true |+ Tag "tz4, preattest" --> begin_test accounts - ~algo:Bls + ~default_algo:Bls ~force_preattest_all:true ~force_attest_all:false |+ Tag "non tz4, attest" @@ -357,7 +363,8 @@ let test_consensus_threshold = --> set S.consensus_committee_size 1000 --> set S.consensus_threshold_size req_attestations --> begin_test - ~delegates_with_algo:[("delegate_1", Bls); ("delegate_2", Bls)] + ~bootstrap_info_list: + [make "delegate_1" ~algo:Bls; make "delegate_2" ~algo:Bls] ["delegate_3"] (* Genesis cannot be attested *) --> next_block @@ -411,7 +418,8 @@ let test_include_valid_dal_content = --> set S.Dal.number_of_slots number_of_slots --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~delegates_with_algo:[("delegate_1", Bls); ("delegate_2", Bls)] + ~bootstrap_info_list: + [make "delegate_1" ~algo:Bls; make "delegate_2" ~algo:Bls] ["delegate_3"] --> next_block (* setup companion keys *) diff --git a/src/proto_alpha/lib_protocol/test/integration/test_scenario_slashing.ml b/src/proto_alpha/lib_protocol/test/integration/test_scenario_slashing.ml index 86c9bff73f1a..777467ee79a7 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_scenario_slashing.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_scenario_slashing.ml @@ -197,7 +197,9 @@ let test_delegate_forbidden = init_constants ~blocks_per_cycle:32l () --> (Tag "non tz4" --> begin_test ["delegate"; "bootstrap1"; "bootstrap2"] |+ Tag "tz4" - --> begin_test ~algo:Bls ["delegate"; "bootstrap1"; "bootstrap2"]) + --> begin_test + ~default_algo:Bls + ["delegate"; "bootstrap1"; "bootstrap2"]) --> set_baker "bootstrap1" --> (Tag "Is not forbidden until first denunciation" --> loop 14 (double_bake "delegate") -- GitLab From 817acfe212cf625d439adb6a53991f407ab88dcd Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Wed, 17 Sep 2025 14:39:24 +0200 Subject: [PATCH 03/34] Proto/tests: simple test init cks --- .../consensus/test_companion_key.ml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml index 436ce42cafc9..ce881a0f346b 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml @@ -208,6 +208,30 @@ let update_key ?proof_signer ?force_no_signer ~kind ~ck_name src = | Companion -> update_companion_key ?proof_signer ?force_no_signer ~ck_name src +let test_init_with_cks_for_bootstraps = + let check_finalized_every_block = [(fun _ -> check_all_cks)] in + init_constants () + --> begin_test + ~check_finalized_every_block + ~force_attest_all:true + ~bootstrap_info_list: + [ + make "no_ck"; + make "with_consensus_key" ~consensus_key:(Some Any_algo); + make "with_companion_key" ~companion_key:true; + make "with_both_tz4" ~consensus_key:(Some Bls) ~companion_key:true; + ] + [] + --> exec_unit check_all_cks + (* Bake a bit, check at each block *) + --> next_block + --> next_block + (* With some DAL, to test the companion key *) + --> exec_state (fun (_block, state) -> + Lwt_result.return {state with State.force_attest_all = false}) + --> attest_aggreg_with ~delegates_with_dal:[("with_both_tz4", Z.of_int 7)] [] + --> next_block + let test_simple_register_consensus_and_companion_keys = let bootstrap_accounts = ["bootstrap1"; "bootstrap2"] in let delegate = "delegate" in @@ -1040,6 +1064,8 @@ let test_batch = let tests = tests_of_scenarios @@ [ + ( "Test bootstrap accounts with initial consensus and companion keys", + test_init_with_cks_for_bootstraps ); ( "Simple update ck for delegate", test_simple_register_consensus_and_companion_keys ); ("Register other accounts as ck", test_register_other_accounts_as_ck); -- GitLab From 1fbfdb15421f9955abc84c0e9a6a955b53d536fd Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Thu, 18 Sep 2025 15:37:01 +0200 Subject: [PATCH 04/34] Proto/tests: constants tolerated inactivity --- src/proto_alpha/lib_protocol/test/helpers/constants_helpers.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/proto_alpha/lib_protocol/test/helpers/constants_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/constants_helpers.ml index 08ce382fa9f7..a1697839e4cb 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/constants_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/constants_helpers.ml @@ -19,6 +19,9 @@ module Set = struct (c : t) = {c with delegate_parameters_activation_delay} + let tolerated_inactivity_period tolerated_inactivity_period (c : t) = + {c with tolerated_inactivity_period} + let blocks_per_cycle blocks_per_cycle (c : t) = {c with blocks_per_cycle} let blocks_per_commitment blocks_per_commitment (c : t) = -- GitLab From 92597e5f3a2f61e6e19884e69d669b5d0013fa5e Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Mon, 22 Sep 2025 16:57:57 +0200 Subject: [PATCH 05/34] Proto/tests: init scenarios with given abaab activ. level --- .../test/helpers/scenario_begin.ml | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml index 9073f9d649aa..04ee8b9423f9 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml @@ -145,8 +145,10 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) ?(force_attest_all = false) ?(force_preattest_all = false) ?(check_finalized_every_block = []) ?(disable_default_checks = false) ?(rng_state = Random.State.make_self_init ()) - (default_bootstrap_name_list : string list) : (constants, t) scenarios = - exec (fun (constants : constants) -> + ?(abaab_activation_levels = []) (default_bootstrap_name_list : string list) + : (constants, t) scenarios = + let f abaab_activation_level = + let g constants = let open Lwt_result_syntax in let make_bootstrap_full (bootstrap_info : bootstrap_info) : bootstrap_full_info = @@ -277,10 +279,31 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) ctxt bootstrap_accounts_list in + (* abaab activation level overwrite *) + let abaab_activation_level_overwrite = + match abaab_activation_level with + | None -> return + | Some level -> + fun ctxt -> + let level = + Protocol.Raw_level_repr.of_int32_exn (Int32.of_int level) + in + let cycle_eras = Protocol.Raw_context.cycle_eras ctxt in + let level = + Protocol.Level_repr.level_from_raw ~cycle_eras level + in + let*! ctxt = + Protocol.Storage.All_bakers_attest_activation.add ctxt level + in + return ctxt + in (* Genesis *) - let* block = - Block.genesis_with_parameters ~prepare_context:set_companion parameters + let prepare_context ctxt = + let* ctxt = set_companion ctxt in + let* ctxt = abaab_activation_level_overwrite ctxt in + return ctxt in + let* block = Block.genesis_with_parameters ~prepare_context parameters in let*? init_level = Context.get_level (B block) in (* init state *) let account_map = @@ -375,4 +398,16 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) if not disable_default_checks then check_all_balances () (block, state) else return_unit in - return (block, state)) + return (block, state) + in + exec g + in + match abaab_activation_levels with + | [] -> f None + | _ :: _ -> + fold_tag_f + f + (function + | None -> "abaab initially off" + | Some level -> Format.asprintf "abaab activation at level %d" level) + abaab_activation_levels -- GitLab From 6d258c14e36276c0c2a0368da42593222cdd205b Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Mon, 22 Sep 2025 17:33:21 +0200 Subject: [PATCH 06/34] Proto/tests: refactor bake_until --- .../test/helpers/scenario_bake.ml | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml index 736d0a902f7d..77abbc2a9111 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml @@ -389,10 +389,11 @@ let rec repeat n f acc = repeat (n - 1) f acc (* adopted from tezt/lib_tezos/client.ml *) -let bake_until_level ~target_level : t -> t tzresult Lwt.t = +let bake_until_level ?(log_message = true) ~target_level : t -> t tzresult Lwt.t + = fun (init_block, init_state) -> let open Lwt_result_syntax in - Log.info "Bake until level %d." target_level ; + if log_message then Log.info "Bake until level %d." target_level ; let current_level = Int32.to_int @@ Block.current_level init_block in if target_level < current_level then Test.fail @@ -407,18 +408,27 @@ let bake_until_level ~target_level : t -> t tzresult Lwt.t = ~error_msg:"Expected level=%R, got %L" ; return (final_block, final_state) -let bake_until ~target_cycle condition : t -> t tzresult Lwt.t = +let bake_until condition : t -> t tzresult Lwt.t = fun (init_block, init_state) -> let blocks_per_cycle = Int32.to_int init_block.constants.blocks_per_cycle in - let target_level, str = + let fs = Format.asprintf in + let target_level, log_str = match condition with - | `New_cycle -> (target_cycle * blocks_per_cycle, "first block") - | `Cycle_end -> (((target_cycle + 1) * blocks_per_cycle) - 1, "last block") - | `Cycle_end_but_one -> - (((target_cycle + 1) * blocks_per_cycle) - 2, "last but one block") + | `Level n -> (n, fs "Bake until level %d" n) + | `Cycle (target_cycle, level_cond) -> + let cycle_offset = target_cycle * blocks_per_cycle in + let level, str = + match level_cond with + | `Level n -> (cycle_offset + n, fs "level position %d" n) + | `First_level -> (cycle_offset, "first level") + | `Last_level -> (cycle_offset + blocks_per_cycle - 1, "last level") + | `Before_last_level -> + (cycle_offset + blocks_per_cycle - 2, "level before last level") + in + (level, fs "Bake until cycle %d, %s (level %d)" target_cycle str level) in - Log.info "Bake until cycle %d (level %d); %s" target_cycle target_level str ; - bake_until_level ~target_level (init_block, init_state) + Log.info "%s" log_str ; + bake_until_level ~log_message:false ~target_level (init_block, init_state) (** Bake until a cycle is reached, using [bake] instead of [Block.bake] *) let bake_until_next_cycle : t -> t tzresult Lwt.t = @@ -427,7 +437,7 @@ let bake_until_next_cycle : t -> t tzresult Lwt.t = Int32.to_int @@ Cycle.to_int32 @@ Cycle.succ @@ Block.current_cycle init_block in - bake_until `New_cycle ~target_cycle:next_cycle (init_block, init_state) + bake_until (`Cycle (next_cycle, `First_level)) (init_block, init_state) (** Bake all the remaining blocks of the current cycle *) let bake_until_dawn_of_next_cycle : t -> t tzresult Lwt.t = @@ -435,7 +445,7 @@ let bake_until_dawn_of_next_cycle : t -> t tzresult Lwt.t = let current_cycle = Int32.to_int @@ Cycle.to_int32 @@ Block.current_cycle init_block in - bake_until `Cycle_end ~target_cycle:current_cycle (init_block, init_state) + bake_until (`Cycle (current_cycle, `Last_level)) (init_block, init_state) let bake_until_next_cycle_end_but_one : t -> t tzresult Lwt.t = fun (init_block, init_state) -> @@ -449,7 +459,7 @@ let bake_until_next_cycle_end_but_one : t -> t tzresult Lwt.t = let target_cycle = if Block.last_block_of_cycle init_block then next_cycle else current_cycle in - bake_until `Cycle_end_but_one ~target_cycle (init_block, init_state) + bake_until (`Cycle (target_cycle, `Before_last_level)) (init_block, init_state) (* ======== Operations ======== *) -- GitLab From e4afcebf36be0406a3210f9a8eccca791296ea46 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 23 Sep 2025 10:48:41 +0200 Subject: [PATCH 07/34] Proto/tests: add abaab test file --- manifest/product_octez.ml | 2 ++ .../test/integration/consensus/dune | 3 ++- .../consensus/test_all_bakers_attest.ml | 25 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml diff --git a/manifest/product_octez.ml b/manifest/product_octez.ml index 00be6ea363a6..5440894e2fd1 100644 --- a/manifest/product_octez.ml +++ b/manifest/product_octez.ml @@ -6252,6 +6252,8 @@ end = struct ("test_dal_entrapment", N.(number >= 022)); ("test_companion_key", N.(number >= 023)); ("test_scenario_attestation", N.(number >= 023)); + ( "test_all_bakers_attest", + N.(number >= 024 && name_dash <> "024-PsD5wVTJ") ); ] |> conditional_list in diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/dune b/src/proto_alpha/lib_protocol/test/integration/consensus/dune index 5065c6ad07f5..6302a492f1ea 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/dune +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/dune @@ -44,7 +44,8 @@ test_aggregate test_dal_entrapment test_companion_key - test_scenario_attestation)) + test_scenario_attestation + test_all_bakers_attest)) (executable (name main) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml new file mode 100644 index 000000000000..fa9b7cd7ff98 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml @@ -0,0 +1,25 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2025 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol ((pre)attestations) + Invocation: dune exec src/proto_alpha/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_all_bakers_attest.ml + + Subject: Test all bakers attest feature and activation. +*) + +open Scenario + +let tests = tests_of_scenarios @@ [] + +let () = + register_tests + ~__FILE__ + ~tags:["protocol"; "scenario"; "consensus"; "all_bakers_attest"] + tests -- GitLab From 43b47c46efca2c45b8c602b6f0b589cef548ab36 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 23 Sep 2025 13:38:05 +0200 Subject: [PATCH 08/34] Proto/tests: init bootstrap with balance and delegate Setting a delegate makes the bootstrap a non-baker (which we want to test abaab) --- .../lib_protocol/test/helpers/account.ml | 8 ++ .../lib_protocol/test/helpers/account.mli | 15 +++ .../test/helpers/scenario_begin.ml | 121 +++++++++++++++--- 3 files changed, 126 insertions(+), 18 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/account.ml b/src/proto_alpha/lib_protocol/test/helpers/account.ml index 83aa119bfe1b..44dc27645001 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/account.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/account.ml @@ -189,3 +189,11 @@ let rec make_bootstrap_accounts ?(bootstrap_balances = []) ~bootstrap_consensus_keys accounts | [] -> [] + +let make_bootstrap_accounts_packed = + List.map (fun (account, balance, delegate_to, consensus_key) -> + make_bootstrap_account + ?balance:(Option.map Tez.of_mutez_exn balance) + ~delegate_to + ~consensus_key + account) diff --git a/src/proto_alpha/lib_protocol/test/helpers/account.mli b/src/proto_alpha/lib_protocol/test/helpers/account.mli index ae7c7a933324..c561267068e6 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/account.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/account.mli @@ -118,6 +118,10 @@ val make_bootstrap_account : [bootstrap_balances], [bootstrap_delegations] and [bootstrap_consensus_keys] to create a list of {!Parameters.bootstrap_account} using [make_bootstrap_account]. + The balances, delegations and consensus keys are given in the same order as the + [accounts], and if they get exhausted, the following bootstrap accounts will be + initialized with default values: {!default_initial_full_balance} for the balance, + and [None] for the delegate and consensus key. *) val make_bootstrap_accounts : ?bootstrap_balances:int64 list -> @@ -125,3 +129,14 @@ val make_bootstrap_accounts : ?bootstrap_consensus_keys:Signature.public_key option list -> t list -> Parameters.bootstrap_account list + +(** [make_bootstrap_accounts_packed accounts_packed] creates bootstrap accounts + from each element [(account, balance, delegate_to, consensus_key)] of the given list, + by calling [make_bootstrap_account ~balance ~delegate_to ~consensus_key account]. *) +val make_bootstrap_accounts_packed : + (t + * int64 option + * Signature.public_key_hash option + * Signature.public_key option) + list -> + Parameters.bootstrap_account list diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml index 04ee8b9423f9..0e2228994ea8 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml @@ -98,7 +98,9 @@ let algo_to_algo = function (* type before applying defaults *) type bootstrap_info = { name : string; + balance_opt : int64 option; algo_opt : algo option; + delegate_opt : string option; consensus_key_algo_opt_opt : algo option option; companion_key_flag_opt : bool option; } @@ -106,14 +108,26 @@ type bootstrap_info = { (** Used to build bootstrap detailed info. @param algo defines the algorithm to use for the given bootstrap. Set to [Any_algo] to choose one randomly. + @param balance is the initial balance of the bootstrap account. Defaults to + whatever {!Account.make_bootstrap_accounts} sets it to, which should be + {!Default_parameters.Internal_for_tests.bootstrap_balance} + @param delegate is the name of the initial delegate of the account. If set, then the + bootstrap account will not be a self delegate. It cannot be set at the same time as the consensus key. @param consensus_key [None] means that the bootstrap account does not have a consensus key. [Some algo] will set a consensus key with the given algo. @param companion_key is a flag that sets a BLS companion key iff the parameter is set to [true]. *) -let make ?algo ?consensus_key ?companion_key name = +let make ?algo ?balance ?delegate ?consensus_key ?companion_key name = + (match (delegate, consensus_key) with + | Some _, Some _ -> + Stdlib.failwith + "Cannot set both delegate and consensus key for bootstrap account." + | _ -> ()) ; { name; + balance_opt = balance; algo_opt = algo; + delegate_opt = delegate; consensus_key_algo_opt_opt = consensus_key; companion_key_flag_opt = companion_key; } @@ -122,6 +136,8 @@ let make ?algo ?consensus_key ?companion_key name = type bootstrap_full_info = { name : string; algo : algo; + balance_opt : int64 option; + delegate_opt : string option; consensus_key_algo_opt : algo option; companion_key_flag : bool; } @@ -129,11 +145,33 @@ type bootstrap_full_info = { (* type after creating accounts *) type bootstrap_accounts = { name : string; - delegate : Account.t; + balance : int64 option; + account : Account.t; + delegate : string option; consensus_key : Account.t option; companion_key : Account.t option; } +let pp_bootstrap_info fmt (info : bootstrap_accounts) = + let fs = Format.asprintf in + let consensus_key = + Option.map + (fun (x : Account.t) -> + fs " (consensus key: %a)" Signature.Public_key_hash.pp x.pkh) + info.consensus_key + in + let delegate = Option.map (fun x -> fs " (delegate: %s)" x) info.delegate in + Format.fprintf + fmt + "%s: %a%a%a" + info.name + Signature.Public_key_hash.pp + info.account.pkh + Format.(pp_print_option pp_print_string) + consensus_key + Format.(pp_print_option pp_print_string) + delegate + (** Initialize the test, given some initial parameters. [algo] defines the algorithm used for the [delegates_name_list]. If not set, a random algorithm is selected for each. @@ -154,6 +192,8 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) bootstrap_full_info = { name = bootstrap_info.name; + balance_opt = bootstrap_info.balance_opt; + delegate_opt = bootstrap_info.delegate_opt; algo = Option.value ~default:default_algo bootstrap_info.algo_opt; consensus_key_algo_opt = Option.value @@ -169,6 +209,8 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) make_bootstrap_full { name; + balance_opt = None; + delegate_opt = None; algo_opt = None; consensus_key_algo_opt_opt = None; companion_key_flag_opt = None; @@ -191,7 +233,7 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) let bootstrap_accounts_list = List.map (fun x -> - let delegate = + let account = Account.new_account ?algo:(algo_to_algo x.algo) ~rng_state () in let consensus_key = @@ -204,22 +246,43 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) if not x.companion_key_flag then None else Some (Account.new_account ~algo:Bls ~rng_state ()) in - {name = x.name; delegate; consensus_key; companion_key}) + { + name = x.name; + balance = x.balance_opt; + account; + delegate = x.delegate_opt; + consensus_key; + companion_key; + }) bootstrap_info_list in (* Setup the bootstrap accounts in the parameters *) - let bootstrap_accounts = - List.map (fun a -> a.delegate) bootstrap_accounts_list + let get_consensus_key_pk_opt = + fun a -> Option.map (fun x -> x.Account.pk) a.consensus_key + in + let get_delegate_pkh_opt = + fun a -> + Option.map + (fun delegate_name -> + let delegate = + Stdlib.List.find + (fun x -> String.equal x.name delegate_name) + bootstrap_accounts_list + in + delegate.account.pkh) + a.delegate in - let bootstrap_consensus_keys = + let bootstrap_accounts_packed = List.map - (fun a -> Option.map (fun x -> x.Account.pk) a.consensus_key) + (fun a -> + ( a.account, + a.balance, + get_delegate_pkh_opt a, + get_consensus_key_pk_opt a )) bootstrap_accounts_list in let bootstrap_accounts = - Account.make_bootstrap_accounts - ~bootstrap_consensus_keys - bootstrap_accounts + Account.make_bootstrap_accounts_packed bootstrap_accounts_packed in let parameters = Tezos_protocol_alpha_parameters.Default_parameters @@ -227,6 +290,10 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) ~bootstrap_accounts constants in + Log.info + "Starting chain with bootstrap accounts:@.%a@." + (Format.pp_print_list ~pp_sep:Format.pp_print_newline pp_bootstrap_info) + bootstrap_accounts_list ; (* Hack-in the companion keys in the context *) let set_companion ctxt = List.fold_left_es @@ -234,7 +301,7 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) match bootstrap.companion_key with | None -> return ctxt | Some ck -> - let key = bootstrap.delegate.Account.pkh in + let key = bootstrap.account.Account.pkh in (* Add the companion key to the global cks storage *) let*! ctxt = Protocol.Storage.Consensus_keys.add ctxt ck.pkh in (* Set the companion key for the bootstrap *) @@ -312,10 +379,24 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) let name = bootstrap_account.name in let contract = Protocol.Alpha_context.Contract.Implicit - bootstrap_account.delegate.pkh + bootstrap_account.account.pkh in - let liquid = Account.default_initial_spendable_balance in - let init_staked = Account.default_initial_staked_balance in + let initial_full = + Option.map Tez.of_mutez bootstrap_account.balance + |> Option.value ~default:Account.default_initial_full_balance + in + let delegate = + Option.value ~default:name bootstrap_account.delegate + in + let self_delegate = String.equal delegate name in + let init_staked = + if not self_delegate then Tez.zero + else + Account.bootstrap_initial_staked_balance + ~constants + ~initial_full_balance:initial_full + in + let liquid = Tez.(initial_full -! init_staked) in let frozen_deposits = Frozen_tez.init init_staked name name in let frozen_rights = List.fold_left @@ -336,19 +417,23 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) (* by construction, the companion keys built previously are BLS *)) bootstrap_account.companion_key in + let last_seen_activity = + if self_delegate then + Some Cycle.(add root constants.consensus_rights_delay) + else None + in let account = init_account ~name ~revealed:true - ~delegate:name + ~delegate ~pkh ~contract ~parameters:default_params ~liquid ~frozen_deposits ~frozen_rights - ~last_seen_activity: - Cycle.(add root constants.consensus_rights_delay) + ?last_seen_activity ?consensus_key ?companion_key () -- GitLab From c6a07a14cfcf15702effe72705d7761e4e6f1b9f Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Mon, 29 Sep 2025 10:46:31 +0200 Subject: [PATCH 09/34] Proto/tests: move activity check functions --- .../lib_protocol/test/helpers/log_helpers.ml | 2 ++ .../lib_protocol/test/helpers/scenario.ml | 1 + .../test/helpers/scenario_activity.ml | 22 +++++++++++++++++++ .../integration/test_scenario_deactivation.ml | 14 ------------ 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/log_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/log_helpers.ml index 2c25ae79e776..c0555a940931 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/log_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/log_helpers.ml @@ -22,3 +22,5 @@ let batch_color = Log.Color.(BG.green ++ FG.black) let assert_block_color = Log.Color.(BG.blue ++ FG.gray) let tez_color = Log.Color.FG.bright_white + +let check_color = Log.Color.FG.gray diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario.ml index f5c67b616189..b4a7309084a9 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario.ml @@ -16,3 +16,4 @@ include Scenario_begin include Scenario_constants include Scenario_bake include Scenario_attestation +include Scenario_activity diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_activity.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_activity.ml index 30598ac72833..6521245d4eb9 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_activity.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_activity.ml @@ -46,3 +46,25 @@ let update_activity name state current_activity_cycle : State.t = name (update_activity_account state.constants current_activity_cycle) state + +let check_is_active ~loc src_name = + let open Lwt_result_syntax in + Scenario_dsl.exec_unit @@ fun (block, state) -> + Log.info + ~color:Log_helpers.check_color + "Check baker activity: [active] \"%s\"" + src_name ; + let src = State.find_account src_name state in + let* b = Context.Delegate.deactivated (B block) src.pkh in + Assert.is_true ~loc (not b) + +let check_is_not_active ~loc src_name = + let open Lwt_result_syntax in + Scenario_dsl.exec_unit @@ fun (block, state) -> + Log.info + ~color:Log_helpers.check_color + "Check baker activity: [not active] \"%s\"" + src_name ; + let src = State.find_account src_name state in + let* b = Context.Delegate.deactivated (B block) src.pkh in + Assert.is_true ~loc b diff --git a/src/proto_alpha/lib_protocol/test/integration/test_scenario_deactivation.ml b/src/proto_alpha/lib_protocol/test/integration/test_scenario_deactivation.ml index 680c5205f85c..d4b0d64e650d 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_scenario_deactivation.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_scenario_deactivation.ml @@ -17,20 +17,6 @@ open State_account open Tez_helpers.Ez_tez open Scenario -let check_is_active ~loc src_name = - let open Lwt_result_syntax in - exec_unit @@ fun (block, state) -> - let src = State.find_account src_name state in - let* b = Context.Delegate.deactivated (B block) src.pkh in - Assert.is_true ~loc (not b) - -let check_is_not_active ~loc src_name = - let open Lwt_result_syntax in - exec_unit @@ fun (block, state) -> - let src = State.find_account src_name state in - let* b = Context.Delegate.deactivated (B block) src.pkh in - Assert.is_true ~loc b - let check_rights_aux ~loc ~expect_rights src_name = exec_unit @@ fun (block, state) -> let src = State.find_account src_name state in -- GitLab From 2ed85d818f8c8c2549e6599e81980a4b9f7a6a39 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Wed, 1 Oct 2025 14:51:27 +0200 Subject: [PATCH 10/34] Proto/tests: add grandgrandparent to state This is unfortunate, but necessary because of end of cycle shenanigans --- src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml | 1 + src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml | 3 ++- src/proto_alpha/lib_protocol/test/helpers/state.ml | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml index 77abbc2a9111..f9b67e114e36 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml @@ -369,6 +369,7 @@ let finalize_block_ : t_incr -> t tzresult Lwt.t = check_finalized_current_block = []; previous_metadata = Some metadata; grandparent = previous_block; + grandgrandparent = state.grandparent; } in return (block, state) diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml index 0e2228994ea8..9ad0f4e2be36 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml @@ -473,10 +473,11 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) check_finalized_current_block = []; previous_metadata = None; operation_mode = Bake; - (* The grandparent is only used to get the consensus key, so it is + (* The (grand)grandparent(s) is only used to get the consensus key, so it is fine to set it to Genesis here. If needed in the future, an option type would be more appropriate. *) grandparent = block; + grandgrandparent = block; } in let* () = diff --git a/src/proto_alpha/lib_protocol/test/helpers/state.ml b/src/proto_alpha/lib_protocol/test/helpers/state.ml index 864da4b9a20d..7b3832cf6caa 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/state.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/state.ml @@ -50,6 +50,7 @@ type t = { previous_metadata : Block.full_metadata option; operation_mode : operation_mode; grandparent : Block.t; + grandgrandparent : Block.t; } (** Expected number of cycles before staking parameters get applied *) -- GitLab From 2ef4faee689eca6d229fb40b942662f8a0655825 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 23 Sep 2025 17:10:05 +0200 Subject: [PATCH 11/34] Proto/tests: abaab activation test --- src/proto_alpha/lib_plugin/RPC.ml | 3 + .../test/helpers/constants_helpers.ml | 10 + .../test/helpers/scenario_attestation.ml | 22 +- .../test/helpers/scenario_base.ml | 6 + .../test/helpers/scenario_begin.ml | 20 +- .../consensus/test_all_bakers_attest.ml | 455 +++++++++++++++++- 6 files changed, 499 insertions(+), 17 deletions(-) diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index 00a0c270c4be..1bbd6fb8d3c2 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -4389,6 +4389,9 @@ let consecutive_round_zero ctxt block = let stake_info ctxt block = RPC_context.make_call0 S.stake_info ctxt block () () +let tz4_baker_number_ratio ctxt ?cycle block = + RPC_context.make_call0 S.tz4_baker_number_ratio ctxt block cycle () + let rpc_services = register () ; RPC_directory.merge rpc_services !Registration.patched_services diff --git a/src/proto_alpha/lib_protocol/test/helpers/constants_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/constants_helpers.ml index a1697839e4cb..8439082da1bf 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/constants_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/constants_helpers.ml @@ -119,6 +119,16 @@ module Set = struct module Dal = struct let number_of_slots number_of_slots (c : t) = dal {c.dal with number_of_slots} c + + let cryptobox_parameters cryptobox_parameters (c : t) = + dal {c.dal with cryptobox_parameters} c + + module Cryptobox_parameters = struct + let number_of_shards number_of_shards (c : t) = + cryptobox_parameters + {c.dal.cryptobox_parameters with number_of_shards} + c + end end let sc_rollup sc_rollup (c : t) = {c with sc_rollup} diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_attestation.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_attestation.ml index 7f012a6bc74b..74cd59379f73 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_attestation.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_attestation.ml @@ -378,14 +378,9 @@ let attest_with_all_ : t -> t tzresult Lwt.t = RPC.Attestation_rights.delegate; consensus_key = _; first_slot = _; - attesting_power; + attesting_power = _; } -> - Tezt.Check.( - (attesting_power > 0) - int - ~__LOC__ - ~error_msg:"Attestation power should be greater than 0, got %L") ; let* is_forbidden = Context.Delegate.is_forbidden (B block) delegate in @@ -603,14 +598,9 @@ let preattest_with_all_ ?payload_round : t_incr -> t_incr tzresult Lwt.t = Plugin.RPC.Attestation_rights.delegate; consensus_key = _; first_slot = _; - attesting_power; + attesting_power = _; } -> - Tezt.Check.( - (attesting_power > 0) - int - ~__LOC__ - ~error_msg:"Attestation power should be greater than 0, got %L") ; let* is_forbidden = Context.Delegate.is_forbidden (I incr) delegate in return (not is_forbidden)) delegates_rights @@ -670,3 +660,11 @@ let preattest_with_all_ ?payload_round : t_incr -> t_incr tzresult Lwt.t = state in return (incr, state) + +let force_attest_all flag = + exec_state (fun (_block, state) -> + Lwt_result.return {state with force_attest_all = flag}) + +let force_preattest_all flag = + exec_state (fun (_block, state) -> + Lwt_result.return {state with force_preattest_all = flag}) diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_base.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_base.ml index cc2cfcea4656..239f227d9076 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_base.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_base.ml @@ -68,6 +68,12 @@ let exclude_bakers bakers : (t, t) scenarios = return {state with State.baking_policy = Some (Block.Excluding bakers_pkh)}) +(** Reset the baking policy to [None], i.e the default policy *) +let reset_baking_policy : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_block, state) -> + return {state with State.baking_policy = None}) + let set_payload_round (payload_round : int option) : (t, t) scenarios = let open Lwt_result_syntax in exec_state (fun (_block, state) -> return {state with State.payload_round}) diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml index 9ad0f4e2be36..1112568b0f62 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml @@ -85,14 +85,20 @@ let init_constants ?(default = Test) ?(reward_per_block = 0L) (Protocol.Issuance_bonus_repr.max_bonus_parameter_of_Q_exn Q.zero) else Empty -type algo = Any_algo | Ed25519 | Secp256k1 | P256 | Bls +type algo = Any_algo | Ed25519 | Secp256k1 | P256 | Bls | Not_Bls -let algo_to_algo = function +let algo_to_algo ~rng_state = function | Ed25519 -> Some Signature.Ed25519 | Secp256k1 -> Some Secp256k1 | P256 -> Some P256 | Bls -> Some Bls | Any_algo -> None + | Not_Bls -> ( + match Random.State.int rng_state 3 with + | 0 -> Some Signature.Ed25519 + | 1 -> Some Secp256k1 + | 2 -> Some P256 + | _ -> assert false) (* None = not set, Some None = set to None (not the same) *) (* type before applying defaults *) @@ -234,12 +240,18 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) List.map (fun x -> let account = - Account.new_account ?algo:(algo_to_algo x.algo) ~rng_state () + Account.new_account + ?algo:(algo_to_algo ~rng_state x.algo) + ~rng_state + () in let consensus_key = Option.map (fun algo -> - Account.new_account ?algo:(algo_to_algo algo) ~rng_state ()) + Account.new_account + ?algo:(algo_to_algo ~rng_state algo) + ~rng_state + ()) x.consensus_key_algo_opt in let companion_key = diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml index fa9b7cd7ff98..d4a51aee3810 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml @@ -16,7 +16,460 @@ open Scenario -let tests = tests_of_scenarios @@ [] +(* === Observables === *) +let check_tz4_baker_number_ratio ~loc expected_values = + let open Lwt_result_syntax in + exec_unit (fun (block, _state) -> + Log.info + ~color:Log_helpers.check_color + "Checking tz4 ratio, expecting the following values: [%a]" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt "; ") + Format.pp_print_string) + expected_values ; + let current_cycle = Block.current_cycle block in + List.iteri_es + (fun offset expected -> + let cycle = Protocol.Alpha_context.Cycle.add current_cycle offset in + let* rpc_ratio = + Plugin.RPC.tz4_baker_number_ratio Block.rpc_ctxt ~cycle block + in + Assert.equal + ~loc + String.equal + (Format.asprintf + "Unexpected tz4 baker ratio at cycle %a" + Protocol.Alpha_context.Cycle.pp + cycle) + Format.pp_print_string + expected + rpc_ratio) + expected_values) + +let check_abaab_activation_level ~loc expected_level = + let open Lwt_result_wrap_syntax in + exec_unit (fun (block, _state) -> + Log.info + ~color:Log_helpers.check_color + "Checking activation level for All Bakers Attest, expecting %s" + (match expected_level with + | None -> "none" + | Some level -> Format.asprintf "level %ld" level) ; + let* ctxt = Context.get_alpha_ctxt (B block) in + let (ctxt : Protocol.Raw_context.t) = + Protocol.Alpha_context.Internal_for_tests.to_raw + (ctxt : Protocol.Alpha_context.t) + in + let*@ activation_level = + Protocol.Storage.All_bakers_attest_activation.find ctxt + in + match (activation_level, expected_level) with + | None, None -> return_unit + | Some level, None -> + failwith + "Activation level is set to %a, expected None" + Protocol.Level_repr.pp + level + | None, Some level -> + failwith "Activation level is not set, expected level %ld" level + | Some rpc_level, Some expected -> + let rpc_level = + Protocol.Raw_level_repr.to_int32 rpc_level.Protocol.Level_repr.level + in + Assert.equal_int32 ~loc expected rpc_level) + +let check_all_bakers_attested ~kind = + let open Lwt_result_syntax in + exec_unit (fun (block, state) -> + let get_active_bakers block = + (* gets the stake info of the block's cycle. It includes all active + bakers with a stake. *) + let* _, bakers = Plugin.RPC.stake_info Block.rpc_ctxt block in + return (List.map fst bakers) + in + let* active_bakers = + match kind with + | Attestation -> + if Block.last_block_of_cycle state.State.grandparent then + get_active_bakers state.State.grandgrandparent + else get_active_bakers state.State.grandparent + | Preattestation -> + if Block.last_block_of_cycle block then + get_active_bakers state.State.grandparent + else get_active_bakers block + in + Log.info + ~color:Log_helpers.check_color + "Checking all bakers %s. Expected committee: %a" + (match kind with + | Attestation -> "attested the previous block" + | Preattestation -> "preattested the current block") + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") + Format.pp_print_string) + (List.map + (fun (x : Protocol.Alpha_context.Consensus_key.t) -> + fst (State.find_account_from_pkh x.delegate state)) + active_bakers) ; + let active_bakers_tz4, active_bakers_non_tz4 = + List.partition + (fun (x : Protocol.Alpha_context.Consensus_key.t) -> + match x.consensus_pkh with Bls _ -> true | _ -> false) + active_bakers + in + let* () = + List.iter_es + (fun (x : Protocol.Alpha_context.Consensus_key.t) -> + check_attestation_metadata + ~kind + x.delegate + x.consensus_pkh + (Stdlib.Option.get state.State.previous_metadata) + (block, state)) + active_bakers_non_tz4 + in + check_attestation_aggregate_metadata + ~kind + active_bakers_tz4 + (Stdlib.Option.get state.State.previous_metadata) + (block, state)) + +let check_all_bakers_preattested = + check_all_bakers_attested ~kind:Preattestation + +let check_all_bakers_attested = check_all_bakers_attested ~kind:Attestation + +(* === Tests === *) + +(* The activation level should only be set if more than half of the registered bakers use + BLS to sign. There are four ways to trigger this: + - an existing registered non-tz4 baker registers a tz4 consensus key + - a tz4 account starts baking + - an existing registered non-tz4 baker gets deactivated + - an existing registered non-tz4 bakers unstakes and gets removed from the consensus. + The storage update is done at the end of the cycle. + If a new tz4 starts baking, but then a tz4 also stops baking (different block but same cycle), + then the feature does not activate. + On the activation cycle, there is at least half of the bakers that *actively* sign with a tz4. + On the previous cycle, there is strictly less. In other words, even if there is a delay + to activate a tz4, there is no further delay to activate the feature. + What should be observed is that small bakers can attest after the feature, + but not (or rarely) before + The deactivation case is done in [test_activation_threshold_with_deactivated_baker] +*) +let test_activation_threshold = + let all_bakers_attest_activation_threshold = + Default_parameters.constants_mainnet.all_bakers_attest_activation_threshold + in + let big = 800_000_000_000_000L in + (* 800M tez *) + let small = + Tez_helpers.to_mutez Default_parameters.constants_mainnet.minimal_stake + |> Int64.mul 2L + (* 12000 tez (2 rolls) *) + in + init_constants () + (* Ensures to set value to mainnet default, regardless of [init_constants] default *) + --> set + S.all_bakers_attest_activation_threshold + all_bakers_attest_activation_threshold + (* set consensus_committee_size very low to make small bakers very unlikely + to have any slots before abaab, making observation easier. + It should still be higher than the number of DAL slots. *) + --> set S.consensus_committee_size 20 + (* this requires the number of DAL shards to be reduced *) + --> set S.Dal.Cryptobox_parameters.number_of_shards 10 + (* set threshold size to 0, making attestations not mandatory *) + --> set S.consensus_threshold_size 0 + (* set a reasonable, human friendly number of blocks per cycle *) + --> set S.blocks_per_cycle 10l + (* set inactivity threshold to very high values, so that + they never get deactivated *) + --> set S.tolerated_inactivity_period 99 + (* Begin test: setup different profiles + 7 bakers, 4 non-BLS, 3 BLS, threshold is not reached yet. *) + --> begin_test + ~force_attest_all:true + ~bootstrap_info_list: + [ + (* bakers *) + make "baker_big" ~algo:Not_Bls ~balance:big; + make "baker_small_1" ~algo:Not_Bls ~balance:small; + make "baker_small_2" ~algo:Not_Bls ~balance:small; + make "tz4_baker_big" ~algo:Bls ~balance:big; + make "tz4_baker_small" ~algo:Bls ~balance:small; + make + "non_tz4_with_tz4_ck_baker_big" + ~algo:Not_Bls + ~consensus_key:(Some Bls) + ~balance:big; + make + "tz4_with_non_tz4_ck_baker_big" + ~algo:Bls + ~consensus_key:(Some Not_Bls) + ~balance:big; + (* delegators *) + make + "tz4_delegator_big" + ~algo:Bls + ~balance:big + ~delegate:"non_tz4_with_tz4_ck_baker_big"; + make + "tz4_delegator_small" + ~algo:Bls + ~balance:small + ~delegate:"baker_big"; + ] + [] + (* 3/7 = 42.8571%. We can check for the current cycle and the next two + (because consensus_rights_delay = 2). + Note: the RPC doesn't round to the nearest, it's always flooring. + *) + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["42.85%"; "42.85%"; "42.85%"] + (* And the activation level is not set yet *) + --> check_abaab_activation_level ~loc:__LOC__ None + (* Check also at next cycle *) + --> next_cycle (* Cycle 1, level pos 0: level 10 *) + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* Check that not all bakers attest *) + (* Delegators overdelegate, so they don't count. + Total stake = N = 2_400_036_000 tez * 11/20 + Small staker has a stake of 12_000 tez * 11/20. + Probability that a given small staker has a slot (out of the 20 available slots): + 1 - (1 - 12000/N) ^ 20 = p + Probability that all three small bakers have a slot for the given block at the same + time: p^3 = 10^-12 *) + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_attested + --> (Tag "add and remove tz4" + (* Case where the feature does not activate: we add a tz4, then remove a tz4 in + the same cycle. The feature does not activate. *) + --> add_account ~algo:Bls "consensus_tz4" + --> add_account ~algo:P256 "consensus_non_tz4" + (* First, add a tz4 consensus key to a non tz4 baker *) + --> update_consensus_key ~ck_name:"consensus_tz4" "baker_big" + (* Bake a block, bide your time *) + --> next_block + (* Then, add a non-tz4 consensus key to a tz4 baker *) + --> update_consensus_key ~ck_name:"consensus_non_tz4" "tz4_baker_small" + (* Check RPCs *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* Check RPCs next cycle too *) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* Below are cases where the feature activates *) + |+ (Tag "new tz4 baker" + (* We register a tz4 delegator as a delegate. This should put the ratio + to 50%, which should be enough to trigger the feature *) + --> set_delegate "tz4_delegator_small" (Some "tz4_delegator_small") + --> stake + "tz4_delegator_small" + (Amount (Tez_helpers.of_mutez 10_000_000_000L)) + (* Nothing changed yet *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* next cycle *) + --> next_cycle (* Cycle 2, level pos 0: level 20 *) + (* The distribution for cycle 4 should have been done now, so we should see an activation + at the beginning of cycle 4. + 4 tz4 bakers out of 8 total bakers: 50% *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + (* Wait until activation *) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["50.00%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + |+ Tag "new tz4 consensus key" + --> add_account ~algo:Bls "consensus_tz4" + --> update_consensus_key ~ck_name:"consensus_tz4" "baker_small_1" + (* Nothing changed yet *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* next cycle *) + --> next_cycle (* Cycle 2, level pos 0: level 20 *) + (* The distribution for cycle 4 should have been done now, so we should see an activation + at the beginning of cycle 4. + 4 tz4 bakers out of 7 total bakers: 57.1428% *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "57.14%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + --> (no_tag + (* Wait until activation *) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "57.14%"; "57.14%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["57.14%"; "57.14%"; "57.14%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + |+ Tag "go below threshold but still activate" + --> add_account ~algo:P256 "consensus_non_tz4" + --> update_consensus_key + ~ck_name:"consensus_non_tz4" + "tz4_baker_big" + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "57.14%"; "42.85%"] + (* We still activate *) + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["57.14%"; "42.85%"; "42.85%"] + (* We still activate *) + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l)) + |+ Tag "non-tz4 baker unstake all" + --> unstake "baker_small_2" All + (* Nothing changed yet *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* next cycle *) + --> next_cycle (* Cycle 2, level pos 0: level 20 *) + (* The distribution for cycle 4 should have been done now, so we should see an activation + at the beginning of cycle 4. + 3 tz4 bakers out of 6 total bakers: 50% *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + (* Wait until activation *) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["50.00%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l)) + --> + (* The feature *just* activated. The last baked block can be attested by all + bakers already. *) + force_attest_all true --> force_preattest_all true + --> set_baked_round ~payload_round:0 1 + --> next_block --> check_all_bakers_attested + --> check_all_bakers_preattested + --> exec bake_until_dawn_of_next_cycle + --> check_all_bakers_attested --> check_all_bakers_preattested + --> next_block --> check_all_bakers_attested + --> check_all_bakers_preattested) + +let test_activation_threshold_with_deactivated_baker = + let all_bakers_attest_activation_threshold = + Default_parameters.constants_mainnet.all_bakers_attest_activation_threshold + in + let balance = 4_000_000_000_000L in + (* 4M tez *) + init_constants () + (* Ensures to set value to mainnet default, regardless of [init_constants] default *) + --> set + S.all_bakers_attest_activation_threshold + all_bakers_attest_activation_threshold + (* set consensus_committee_size to the default *) + --> set S.consensus_committee_size 7000 + (* set threshold size to 0, making attestations not mandatory *) + --> set S.consensus_threshold_size 0 + (* set a reasonable, human friendly number of blocks per cycle *) + --> set S.blocks_per_cycle 10l + (* set inactivity threshold very low to wait for a baker to be deactivated *) + --> set S.tolerated_inactivity_period 1 + (* Begin test: setup bootstrap accounts + 3 bakers, 2 non-BLS, 1 BLS, threshold is not reached yet. *) + --> begin_test + ~force_attest_all:true + ~bootstrap_info_list: + [ + (* bakers *) + make "baker_1" ~algo:Not_Bls ~balance; + make "baker_2" ~algo:Not_Bls ~balance; + make "tz4_baker" ~algo:Bls ~balance; + ] + [] + (* 1/3 = 33.3333%. We can check for the current cycle and the next two + (because consensus_rights_delay = 2). + Note: the RPC doesn't round to the nearest, it's always flooring. + *) + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["33.33%"; "33.33%"; "33.33%"] + (* And the activation level is not set yet *) + --> check_abaab_activation_level ~loc:__LOC__ None + (* Check also at next cycle *) + --> next_cycle (* Cycle 1, level pos 0: level 10 *) + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["33.33%"; "33.33%"; "33.33%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* make "baker_2" inactive. We have to wait for next cycle because + the baker might have attested the first block of the current cycle. *) + --> dawn_of_next_cycle (* Cycle 1, level pos 9: level 19 *) + --> force_attest_all false --> exclude_bakers ["baker_2"] + (* Wait for inactivation, which should be at cycle 4 *) + --> exec (bake_until (`Cycle (4, `First_level))) + (* Cycle 4, level pos 0: level 40 *) + (* "baker_2" neither baked nor attested for two cycles, it should be deactivated. + It should also be the only deactivated baker since the other bakers baked. *) + --> check_is_not_active ~loc:__LOC__ "baker_2" + --> check_is_active ~loc:__LOC__ "baker_1" + --> check_is_active ~loc:__LOC__ "tz4_baker" + (* The distribution for cycle 6 should have been done now, so we should see an activation + at the beginning of cycle 6. + 1 tz4 bakers out of 2 total bakers: 50% *) + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["33.33%"; "33.33%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 60l) + (* Wait until activation *) + --> next_cycle + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["33.33%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 60l) + --> next_cycle + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["50.00%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 60l) + (* Reset state parameters *) + --> force_attest_all true + --> reset_baking_policy + --> + (* The feature *just* activated. The last baked block can be attested by all + bakers already. *) + force_attest_all true --> force_preattest_all true + --> set_baked_round ~payload_round:0 1 + --> next_block --> check_all_bakers_attested --> check_all_bakers_preattested + --> exec bake_until_dawn_of_next_cycle + --> check_all_bakers_attested --> check_all_bakers_preattested --> next_block + --> check_all_bakers_attested --> check_all_bakers_preattested + +let tests = + tests_of_scenarios + @@ [ + ("Test abaab activation threshold", test_activation_threshold); + ( "Test abaab activation threshold when a non BLS baker gets deactivated", + test_activation_threshold_with_deactivated_baker ); + ] let () = register_tests -- GitLab From 3b26e8e547fa15331acf3657d5113b17ebb73618 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Wed, 1 Oct 2025 14:52:21 +0200 Subject: [PATCH 12/34] Proto/tests: abaab activation level test --- .../consensus/test_all_bakers_attest.ml | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml index d4a51aee3810..8d45364d7722 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml @@ -463,12 +463,111 @@ let test_activation_threshold_with_deactivated_baker = --> check_all_bakers_attested --> check_all_bakers_preattested --> next_block --> check_all_bakers_attested --> check_all_bakers_preattested +let test_activation_level level = + let big = 800_000_000_000_000L in + (* 800M tez *) + let small = + Tez_helpers.to_mutez Default_parameters.constants_mainnet.minimal_stake + |> Int64.mul 2L + (* 12000 tez (2 rolls) *) + in + init_constants () + (* set consensus_committee_size very low to make small bakers very unlikely + to have any slots before abaab, making observation easier. + It should still be higher than the number of DAL slots. *) + --> set S.consensus_committee_size 20 + (* this requires the number of DAL shards to be reduced *) + --> set S.Dal.Cryptobox_parameters.number_of_shards 10 + (* set threshold size to 0, making attestations not mandatory *) + --> set S.consensus_threshold_size 0 + (* set a reasonable, human friendly number of blocks per cycle *) + --> set S.blocks_per_cycle 10l + (* set inactivity period to very high values, so that + bakers never get deactivated *) + --> set S.tolerated_inactivity_period 99 + (* Begin test: setup different profiles + 6 bakers, 2 big, 4 small. *) + --> begin_test + ~force_attest_all:true + ~force_preattest_all:true + ~abaab_activation_levels:[Some level] + ~bootstrap_info_list: + [ + make "big_1" ~algo:Not_Bls ~balance:big; + make "big_2" ~algo:Bls ~balance:big; + make "small_1" ~algo:Not_Bls ~balance:small; + make + "small_2" + ~algo:Not_Bls + ~consensus_key:(Some Bls) + ~balance:small; + make "small_3" ~algo:Bls ~balance:small; + make + "small_4" + ~algo:Bls + ~consensus_key:(Some Not_Bls) + ~balance:small; + ] + [] + (* sanity check *) + --> check_abaab_activation_level ~loc:__LOC__ (Some (Int32.of_int level)) + --> set_baked_round ~payload_round:0 1 + (* next two blocks because cannot attest genesis *) + --> next_block + --> next_block + (* Total stake: N = 1_600_048_000 tez * 11/20 + Probability that a given small staker has a slot (out of the 20 available slots): + 1 - (1 - 12000/N) ^ 20 = p + Probability that all three small bakers have a slot for the given block at the same + time: p^4 = 5.10^-16 *) + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_attested + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_preattested + (* Bake until almost the activation level *) + --> exec (bake_until (`Level (level - 1))) + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_attested + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_preattested + (* Next level: activation level. All bakers can preattest, but attestations + are for the predecessor, which is not under abaab. *) + --> next_block + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_attested + --> check_all_bakers_preattested + (* Next level: abaab is fully activated *) + --> next_block + --> check_all_bakers_attested --> check_all_bakers_preattested + (* We bake a bit, at least a cycle *) + --> loop + 12 + (next_block --> check_all_bakers_attested + --> check_all_bakers_preattested) + +let test_activation_level = + fold_tag_f + test_activation_level + (fun level -> Format.asprintf "level %d" level) + [8; 9; 10; 11; 12] + let tests = tests_of_scenarios @@ [ ("Test abaab activation threshold", test_activation_threshold); ( "Test abaab activation threshold when a non BLS baker gets deactivated", test_activation_threshold_with_deactivated_baker ); + ("Test abaab activation level", test_activation_level); ] let () = -- GitLab From c5f9c0845e08605f17bbbef74f49eaa65b26cbb7 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Thu, 2 Oct 2025 15:45:47 +0200 Subject: [PATCH 13/34] Proto/tests: attestation tests with abaab --- .../lib_protocol/test/helpers/scenario_dsl.ml | 8 +++ .../consensus/test_scenario_attestation.ml | 58 +++++++++++++++---- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_dsl.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_dsl.ml index 8e1d986e5f11..91fbde272c64 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_dsl.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_dsl.ml @@ -191,6 +191,14 @@ let fold_tag : let f (s, x) = Tag s --> f x in fold f +let fold_tag_opt : + ('a -> ('b, 'c) scenarios) -> + (string option * 'a) list -> + ('b, 'c) scenarios = + fun f -> + let f (s, x) = (match s with Some s -> Tag s | None -> Empty) --> f x in + fold f + (** [fold_tag_f f tag l] folds [f] over [l], [tag] returns a tag for each element of [l]. Fails on empty list. *) let fold_tag_f : diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_scenario_attestation.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_scenario_attestation.ml index 2f17886f42a2..f6eb5bae75ee 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_scenario_attestation.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_scenario_attestation.ml @@ -97,7 +97,10 @@ let check_aggregated_committee = let test_attest_simple = init_constants () - --> begin_test ["delegate"; "dummy"] ~force_attest_all:false + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate"; "dummy"] + ~force_attest_all:false --> next_block --> attest_with "delegate" --> next_block (* Sanity checks. The positive checks are done every time there is an attestation or a preattestation. *) @@ -106,7 +109,10 @@ let test_attest_simple = let test_preattest_simple = init_constants () - --> begin_test ["delegate"] ~force_preattest_all:false + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate"] + ~force_preattest_all:false --> set_baked_round 1 --> next_block --> finalize_payload ~payload_round:0 () --> preattest_with "delegate" --> finalize_block @@ -116,7 +122,10 @@ let test_preattest_simple = let test_preattest_less_simple = init_constants () - --> begin_test ["delegate1"; "delegate2"] ~force_preattest_all:false + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate1"; "delegate2"] + ~force_preattest_all:false --> set_baked_round 1 --> next_block --> start_payload --> transfer "delegate1" "delegate2" (Amount (Tez_helpers.of_mutez 100L)) --> transfer "delegate2" "delegate1" (Amount (Tez_helpers.of_mutez 99L)) @@ -129,7 +138,10 @@ let test_preattest_less_simple = let test_attest_all = init_constants () - --> begin_test ["delegate1"; "delegate2"] ~force_attest_all:true + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate1"; "delegate2"] + ~force_attest_all:true --> next_block (* This block does not contain attestations; check next. *) --> next_block (* Sanity checks *) @@ -141,7 +153,10 @@ let test_attest_all = let test_preattest_all = init_constants () - --> begin_test ["delegate1"; "delegate2"] ~force_preattest_all:true + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate1"; "delegate2"] + ~force_preattest_all:true --> set_baked_round ~payload_round:0 1 --> next_block (* Sanity checks *) @@ -154,6 +169,7 @@ let test_preattest_all = let test_attest_aggreg = init_constants () --> begin_test + ~abaab_activation_levels:[Some 0; None] ["delegate1"; "delegate2"] ~default_algo:Bls ~force_attest_all:false @@ -169,6 +185,7 @@ let test_attest_aggreg = let test_preattest_aggreg = init_constants () --> begin_test + ~abaab_activation_levels:[Some 0; None] ["delegate1"; "delegate2"] ~default_algo:Bls ~force_preattest_all:false @@ -199,21 +216,25 @@ let init_constants_for_attestation_rewards = } let test_attestation_rewards = + let abaab_activation_levels = [Some 0; None] in init_constants_for_attestation_rewards (* Default checks are disabled because rewards have been changed *) --> (Tag "not tz4" --> begin_test + ~abaab_activation_levels ["delegate"] ~disable_default_checks:true ~force_attest_all:true |+ Tag "tz4 (solo)" --> begin_test + ~abaab_activation_levels ["delegate"] ~default_algo:Bls ~disable_default_checks:true ~force_attest_all:true |+ Tag "tz4 (with others)" --> begin_test + ~abaab_activation_levels ["delegate"; "bozo1"; "bozo2"] ~default_algo:Bls ~disable_default_checks:true @@ -226,7 +247,10 @@ let test_attestation_rewards = let test_missed_attestations_rewards = init_constants_for_attestation_rewards (* Default checks are disabled because rewards have been changed *) - --> begin_test ["delegate"] ~disable_default_checks:true + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate"] + ~disable_default_checks:true --> snapshot_balances "init" ["delegate"] --> next_block --> (Tag "attest once" --> attest_with "delegate" |+ Tag "no attest" --> noop) @@ -239,6 +263,7 @@ let test_missed_attestations_rewards_tz4 = init_constants_for_attestation_rewards (* Default checks are disabled because rewards have been changed *) --> begin_test + ~abaab_activation_levels:[Some 0; None] ["delegate"; "bozo1"; "bozo2"] ~default_algo:Bls ~disable_default_checks:true @@ -265,6 +290,7 @@ let test_forbidden_delegate_tries_to_attest_but_fails_miserably = in init_constants () --> begin_test + ~abaab_activation_levels:[Some 0; None] ["delegate"; "baker"] ~force_preattest_all:false ~force_attest_all:false @@ -290,6 +316,7 @@ let test_forbidden_delegate_tries_to_attest_but_fails_miserably_tz4_edition = in init_constants () --> begin_test + ~abaab_activation_levels:[Some 0; None] ["delegate"; "baker"; "attester"] ~default_algo:Bls ~force_preattest_all:false @@ -320,27 +347,32 @@ let test_forbidden_delegate_tries_to_attest_but_fails_miserably_tz4_edition = let test_attestations_keep_activation_status = let open Lwt_result_syntax in let accounts = ["delegate"; "baker"; "attester"] in + let abaab_activation_levels = [Some 0; None] in init_constants () --> (Tag "tz4, attest" --> begin_test accounts + ~abaab_activation_levels ~default_algo:Bls ~force_preattest_all:false ~force_attest_all:true |+ Tag "tz4, preattest" --> begin_test accounts + ~abaab_activation_levels ~default_algo:Bls ~force_preattest_all:true ~force_attest_all:false |+ Tag "non tz4, attest" --> begin_test accounts + ~abaab_activation_levels ~force_preattest_all:false ~force_attest_all:true |+ Tag "non tz4, preattest" --> begin_test accounts + ~abaab_activation_levels ~force_preattest_all:true ~force_attest_all:false) --> set_baker ~min_round:1 "baker" @@ -363,6 +395,7 @@ let test_consensus_threshold = --> set S.consensus_committee_size 1000 --> set S.consensus_threshold_size req_attestations --> begin_test + ~abaab_activation_levels:[Some 0; None] ~bootstrap_info_list: [make "delegate_1" ~algo:Bls; make "delegate_2" ~algo:Bls] ["delegate_3"] @@ -379,9 +412,11 @@ let test_consensus_threshold = Assert.expect_error ~loc:__LOC__ errs (function | [ Protocol.Validate_errors.Block.Not_enough_attestations - {required; provided = _}; + {required = _; provided = _}; ] -> - required = Int64.of_int req_attestations + (* TODO ABAAB: check required *) + (* required = Int64.of_int req_attestations *) + true | _ -> false)) next_block --> attest_with "delegate_3" --> next_block @@ -394,9 +429,11 @@ let test_consensus_threshold = Assert.expect_error ~loc:__LOC__ errs (function | [ Protocol.Validate_errors.Block.Not_enough_attestations - {required; provided = _}; + {required = _; provided = _}; ] -> - required = Int64.of_int req_attestations + (* TODO ABAAB: check required *) + (* required = Int64.of_int req_attestations *) + true | _ -> false)) next_block @@ -418,6 +455,7 @@ let test_include_valid_dal_content = --> set S.Dal.number_of_slots number_of_slots --> set S.consensus_rights_delay consensus_rights_delay --> begin_test + ~abaab_activation_levels:[Some 0; None] ~bootstrap_info_list: [make "delegate_1" ~algo:Bls; make "delegate_2" ~algo:Bls] ["delegate_3"] -- GitLab From 128cbc7cb796aa47103694ba64f4c35b8c3171d2 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 7 Oct 2025 13:04:57 +0200 Subject: [PATCH 14/34] Proto/tests: abaab zero threshold activation at level 0 --- .../integration/consensus/test_all_bakers_attest.ml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml index 8d45364d7722..5cb53cf65611 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml @@ -561,6 +561,14 @@ let test_activation_level = (fun level -> Format.asprintf "level %d" level) [8; 9; 10; 11; 12] +let test_activation_with_zero_threshold = + init_constants () + --> set + S.all_bakers_attest_activation_threshold + {numerator = 0; denominator = 1} + --> begin_test ~abaab_activation_levels:[None] ["bootstrap"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 0l) + let tests = tests_of_scenarios @@ [ @@ -568,6 +576,8 @@ let tests = ( "Test abaab activation threshold when a non BLS baker gets deactivated", test_activation_threshold_with_deactivated_baker ); ("Test abaab activation level", test_activation_level); + ( "Test abaab threshold zero activation", + test_activation_with_zero_threshold ); ] let () = -- GitLab From 0620030e954d99bf0bdcd75ff9209350493b540e Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Wed, 8 Oct 2025 15:21:51 +0200 Subject: [PATCH 15/34] Proto/tests: mempool consensus minimal slot with abaab --- tezt/tests/double_consensus.ml | 3 +- tezt/tests/prevalidator.ml | 137 +++++++++++++++++++++------------ 2 files changed, 91 insertions(+), 49 deletions(-) diff --git a/tezt/tests/double_consensus.ml b/tezt/tests/double_consensus.ml index c4d8d8f320a1..c4e3ee6cdfe8 100644 --- a/tezt/tests/double_consensus.ml +++ b/tezt/tests/double_consensus.ml @@ -107,7 +107,8 @@ let double_consensus_init (if Protocol.number protocol >= 024 then JSON.( slots |> as_list |> List.hd |-> "delegates" |> as_list |> List.hd - |-> "rounds" |> as_list) + |-> "attestation_slot") + :: [] else JSON.(slots |> as_list |> List.hd |-> "slots" |> as_list)) in Log.info "Inject valid %s." consensus_name ; diff --git a/tezt/tests/prevalidator.ml b/tezt/tests/prevalidator.ml index 82cf58e1fbd6..e56a6d63548d 100644 --- a/tezt/tests/prevalidator.ml +++ b/tezt/tests/prevalidator.ml @@ -3791,18 +3791,31 @@ module Revamped = struct in unit - let consensus_minimal_slots_feature_flag = + let consensus_minimal_slots_feature_flag ~abaab = Protocol.register_test ~__FILE__ - ~title:"Mempool filters consensus operations with non-minimal slots" + ~title: + (Format.asprintf + "Mempool filters consensus operations with non-minimal slots (abaab \ + %s)" + (if abaab then "on" else "off")) ~tags:[team; "mempool"; "consensus"; "minimal"; "slots"] ~supports:(Protocol.From_protocol 023) @@ fun protocol -> log_step 1 "Initialize node and activate protocol" ; + let pair_to_ratio (num, den) = + let str = "all_bakers_attest_activation_threshold" in + [([str; "numerator"], `Int num); ([str; "denominator"], `Int den)] + in + let abaab_threshold = + if Protocol.number protocol < 024 then [] + else if abaab then pair_to_ratio (0, 1) + else pair_to_ratio (2, 1) + in let* parameter_file = Protocol.write_parameter_file ~base:(Either.Right (protocol, None)) - [(["aggregate_attestation"], `Bool true)] + ([(["aggregate_attestation"], `Bool true)] @ abaab_threshold) in let* node, client = Client.init_with_protocol `Client ~protocol ~parameter_file () @@ -3838,51 +3851,78 @@ module Revamped = struct let* validated, refused = Lwt_list.fold_left_s (fun (validated, refused) level -> - let* attesting_rights = - Operation.Consensus.get_rounds ~level ~protocol client - in - (* TODO ABAAB: this test assumes the rounds are attestation slots, this needs - to be updated with the flag status *) - (* Look for a delegate that has more than one slot *) - let delegate, slots = - let delegate_opt = - Array.find_map - (fun account -> - match - List.assoc_opt - account.Account.public_key_hash - attesting_rights - with - | Some (_ :: _ :: _ as slots) -> Some (account, slots) - | _ -> None) - Account.Bootstrap.keys + if abaab then + let delegate = Account.Bootstrap.keys.(0) in + let* slot = + Operation.Consensus.get_attestation_slot + ~delegate + ~level + ~protocol + client in - match delegate_opt with - | Some (delegate, slots) -> (delegate, slots) - | None -> - Test.fail - "found no delegate with more than one slot at level %d" - level - in - (* Inject an attestation with a minimal slot *) - let* (`OpHash valid_attestation) = - attest_for ~delegate ~level ~slot:(List.hd slots) - in - (* Inject an attestation with a non-minimal slot *) - let* (`OpHash refused_attestation) = - attest_for ~delegate ~level ~slot:(List.nth slots 1) - in - (* Inject a preattestation with a minimal slot *) - let* (`OpHash valid_preattestation) = - preattest_for ~delegate ~level ~slot:(List.hd slots) - in - (* Inject a preattestation with a non-minimal slot *) - let* (`OpHash refused_preattestation) = - preattest_for ~delegate ~level ~slot:(List.nth slots 1) - in - return - ( valid_attestation :: valid_preattestation :: validated, - refused_attestation :: refused_preattestation :: refused )) + (* Inject an attestation with the correct slot *) + let* (`OpHash valid_attestation) = + attest_for ~delegate ~level ~slot + in + (* Inject an attestation with an incorrect slot *) + let* (`OpHash refused_attestation) = + attest_for ~delegate ~level ~slot:(slot + 1) + in + (* Inject a preattestation with the correct slot *) + let* (`OpHash valid_preattestation) = + preattest_for ~delegate ~level ~slot + in + (* Inject a preattestation with an incorrect slot *) + let* (`OpHash refused_preattestation) = + preattest_for ~delegate ~level ~slot:(slot + 1) + in + return + ( valid_attestation :: valid_preattestation :: validated, + refused_attestation :: refused_preattestation :: refused ) + else + let* attesting_rights = + Operation.Consensus.get_rounds ~level ~protocol client + in + (* Look for a delegate that has more than one slot *) + let delegate, slots = + let delegate_opt = + Array.find_map + (fun account -> + match + List.assoc_opt + account.Account.public_key_hash + attesting_rights + with + | Some (_ :: _ :: _ as slots) -> Some (account, slots) + | _ -> None) + Account.Bootstrap.keys + in + match delegate_opt with + | Some (delegate, slots) -> (delegate, slots) + | None -> + Test.fail + "found no delegate with more than one slot at level %d" + level + in + (* Inject an attestation with a minimal slot *) + let* (`OpHash valid_attestation) = + attest_for ~delegate ~level ~slot:(List.hd slots) + in + (* Inject an attestation with a non-minimal slot *) + let* (`OpHash refused_attestation) = + attest_for ~delegate ~level ~slot:(List.nth slots 1) + in + (* Inject a preattestation with a minimal slot *) + let* (`OpHash valid_preattestation) = + preattest_for ~delegate ~level ~slot:(List.hd slots) + in + (* Inject a preattestation with a non-minimal slot *) + let* (`OpHash refused_preattestation) = + preattest_for ~delegate ~level ~slot:(List.nth slots 1) + in + return + ( valid_attestation :: valid_preattestation :: validated, + refused_attestation :: refused_preattestation :: refused )) ([], []) accepted_levels in @@ -4404,4 +4444,5 @@ let register ~protocols = Revamped.request_operations_from_peer protocols ; force_operation_injection protocols ; Revamped.injecting_old_operation_fails protocols ; - Revamped.consensus_minimal_slots_feature_flag protocols + Revamped.consensus_minimal_slots_feature_flag protocols ~abaab:false ; + Revamped.consensus_minimal_slots_feature_flag protocols ~abaab:true -- GitLab From 534ed6093be7a5690df7067b989684aca20133a4 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Thu, 9 Oct 2025 14:51:04 +0200 Subject: [PATCH 16/34] Proto/tests: baker tezt tests with abaab --- tezt/tests/baker_test.ml | 187 ++++++++++++++++++++++++--------------- 1 file changed, 118 insertions(+), 69 deletions(-) diff --git a/tezt/tests/baker_test.ml b/tezt/tests/baker_test.ml index ec617254ace3..34d4582e9ee8 100644 --- a/tezt/tests/baker_test.ml +++ b/tezt/tests/baker_test.ml @@ -39,6 +39,18 @@ let log_step counter msg = let prefix = "step" ^ string_of_int counter in Log.info ~color ~prefix msg +let title_abaab ~abaab title = + Format.asprintf "%s (abaab: %s)" title (if abaab then "on" else "off") + +let abaab_threshold ~abaab ~protocol = + let pair_to_ratio (num, den) = + let str = "all_bakers_attest_activation_threshold" in + [([str; "numerator"], `Int num); ([str; "denominator"], `Int den)] + in + if Protocol.number protocol < 024 then [] + else if abaab then pair_to_ratio (0, 1) + else pair_to_ratio (2, 1) + let bootstrap1, bootstrap2, bootstrap3, bootstrap4, bootstrap5 = Constant.(bootstrap1, bootstrap2, bootstrap3, bootstrap4, bootstrap5) @@ -267,16 +279,26 @@ let baker_remote_test = let* _ = Node.wait_for_level node 3 in unit -let baker_check_consensus_branch = +let baker_check_consensus_branch ~abaab = Protocol.register_test ~__FILE__ - ~title:"Baker check branch in consensus operations" + ~title:(title_abaab ~abaab "Baker check branch in consensus operations") ~tags:[team; "baker"; "grandparent"; "parent"] ~uses:(fun _protocol -> [Constant.octez_agnostic_baker]) @@ fun protocol -> Log.info "Init client and node with protocol %s" (Protocol.name protocol) ; + let* parameter_file = + Protocol.write_parameter_file + ~base:(Right (protocol, None)) + (abaab_threshold ~abaab ~protocol) + in let* node, client = - Client.init_with_protocol `Client ~protocol () ~timestamp:Now + Client.init_with_protocol + `Client + ~protocol + ~parameter_file + () + ~timestamp:Now in let target_level = 5 in @@ -314,17 +336,27 @@ let baker_check_consensus_branch = ops (** Test that blocks are applied only if round >= [force_apply_from_round]. *) -let force_apply_from_round = +let force_apply_from_round ~abaab = Protocol.register_test ~__FILE__ - ~title:"Baker check force apply from round" + ~title:(title_abaab ~abaab "Baker check force apply from round") ~tags:[team; "baker"; "force_apply_from_round"] ~supports:Protocol.(From_protocol 021) ~uses:(fun _protocol -> [Constant.octez_agnostic_baker]) @@ fun protocol -> log_step 1 "initialize a node and a client with protocol" ; + let* parameter_file = + Protocol.write_parameter_file + ~base:(Right (protocol, None)) + (abaab_threshold ~abaab ~protocol) + in let* node, client = - Client.init_with_protocol `Client ~protocol () ~timestamp:Now + Client.init_with_protocol + `Client + ~protocol + ~parameter_file + () + ~timestamp:Now in log_step 2 "wait for level 1" ; @@ -654,22 +686,23 @@ let check_consensus_operations ?expected_attestations_committee in unit -let simple_attestation_aggregation ~remote_mode protocol = +let simple_attestation_aggregation ~abaab ~remote_mode protocol = log_step 1 "Initialize a node and a client with protocol" ; let consensus_rights_delay = 1 in let* parameter_file = Protocol.write_parameter_file ~base:(Right (protocol, None)) - [ - (["allow_tz4_delegate_enable"], `Bool true); - (["aggregate_attestation"], `Bool true); - (* Diminish some constants to activate consensus keys faster *) - (["blocks_per_cycle"], `Int 2); - (["nonce_revelation_threshold"], `Int 1); - (["consensus_rights_delay"], `Int consensus_rights_delay); - (["cache_sampler_state_cycles"], `Int (consensus_rights_delay + 3)); - (["cache_stake_distribution_cycles"], `Int (consensus_rights_delay + 3)); - ] + ([ + (["allow_tz4_delegate_enable"], `Bool true); + (["aggregate_attestation"], `Bool true); + (* Diminish some constants to activate consensus keys faster *) + (["blocks_per_cycle"], `Int 2); + (["nonce_revelation_threshold"], `Int 1); + (["consensus_rights_delay"], `Int consensus_rights_delay); + (["cache_sampler_state_cycles"], `Int (consensus_rights_delay + 3)); + (["cache_stake_distribution_cycles"], `Int (consensus_rights_delay + 3)); + ] + @ abaab_threshold ~abaab ~protocol) in let* node, client = Client.init_with_protocol @@ -735,29 +768,31 @@ let simple_attestation_aggregation ~remote_mode protocol = unit (* Test that the baker aggregates eligible attestations.*) -let simple_attestations_aggregation_local_context = +let simple_attestations_aggregation_local_context ~abaab = Protocol.register_test ~__FILE__ - ~title:"Simple attestations aggregation local context" + ~title:(title_abaab ~abaab "Simple attestations aggregation local context") ~tags:[team; "baker"; "attestation"; "aggregation"; "local"] ~supports:Protocol.(From_protocol 023) ~uses:(fun _protocol -> [Constant.octez_agnostic_baker]) - @@ fun protocol -> simple_attestation_aggregation ~remote_mode:false protocol + @@ fun protocol -> + simple_attestation_aggregation ~abaab ~remote_mode:false protocol (* Test that the baker aggregates eligible attestations.*) -let simple_attestations_aggregation_remote_node = +let simple_attestations_aggregation_remote_node ~abaab = Protocol.register_test ~__FILE__ - ~title:"Simple attestations aggregation remote node" + ~title:(title_abaab ~abaab "Simple attestations aggregation remote node") ~tags:[team; "baker"; "attestation"; "aggregation"; "remote"] ~supports:Protocol.(From_protocol 023) ~uses:(fun _protocol -> [Constant.octez_agnostic_baker]) - @@ fun protocol -> simple_attestation_aggregation ~remote_mode:true protocol + @@ fun protocol -> + simple_attestation_aggregation ~abaab ~remote_mode:true protocol -let prequorum_check_levels = +let prequorum_check_levels ~abaab = Protocol.register_test ~__FILE__ - ~title:"prequorum monitoring check operations level" + ~title:(title_abaab ~abaab "prequorum monitoring check operations level") ~tags:[team; "prequorum"; "monitoring"; "check"] ~uses:(fun _protocol -> [Constant.octez_agnostic_baker]) @@ fun protocol -> @@ -768,7 +803,8 @@ let prequorum_check_levels = let* parameter_file = Protocol.write_parameter_file ~base:(Left parameter_file) - [(["minimal_block_delay"], `String "4")] + ([(["minimal_block_delay"], `String "4")] + @ abaab_threshold ~abaab ~protocol) in let* node, client = Client.init_with_protocol @@ -877,28 +913,29 @@ let z_of_bool_vector dal_attestation = in Array.fold_left aux (0, 0) dal_attestation |> fst |> Z.of_int -let attestations_aggregation_on_reproposal ~remote_mode protocol = +let attestations_aggregation_on_reproposal ~abaab ~remote_mode protocol = let consensus_rights_delay = 1 in let consensus_committee_size = 256 in let* parameter_file = Protocol.write_parameter_file ~base:(Right (protocol, None)) - [ - (["allow_tz4_delegate_enable"], `Bool true); - (["aggregate_attestation"], `Bool true); - (* Using custom consensus constants to be able to trigger reproposals *) - (["consensus_committee_size"], `Int consensus_committee_size); - (["consensus_threshold_size"], `Int 70); - (* Diminish some constants to activate consensus keys faster, + ([ + (["allow_tz4_delegate_enable"], `Bool true); + (["aggregate_attestation"], `Bool true); + (* Using custom consensus constants to be able to trigger reproposals *) + (["consensus_committee_size"], `Int consensus_committee_size); + (["consensus_threshold_size"], `Int 70); + (* Diminish some constants to activate consensus keys faster, and make round durations as small as possible *) - (["minimal_block_delay"], `String "4"); - (["delay_increment_per_round"], `String "0"); - (["blocks_per_cycle"], `Int 2); - (["nonce_revelation_threshold"], `Int 1); - (["consensus_rights_delay"], `Int consensus_rights_delay); - (["cache_sampler_state_cycles"], `Int (consensus_rights_delay + 3)); - (["cache_stake_distribution_cycles"], `Int (consensus_rights_delay + 3)); - ] + (["minimal_block_delay"], `String "4"); + (["delay_increment_per_round"], `String "0"); + (["blocks_per_cycle"], `Int 2); + (["nonce_revelation_threshold"], `Int 1); + (["consensus_rights_delay"], `Int consensus_rights_delay); + (["cache_sampler_state_cycles"], `Int (consensus_rights_delay + 3)); + (["cache_stake_distribution_cycles"], `Int (consensus_rights_delay + 3)); + ] + @ abaab_threshold ~abaab ~protocol) in let* node, client = Client.init_with_protocol @@ -1159,30 +1196,37 @@ let attestations_aggregation_on_reproposal ~remote_mode protocol = unit (* Test that the baker correctly aggregates eligible attestations on reproposals.*) -let attestations_aggregation_on_reproposal_local_context = +let attestations_aggregation_on_reproposal_local_context ~abaab = Protocol.register_test ~__FILE__ - ~title:"Attestations aggregation on reproposal local context" + ~title: + (title_abaab + ~abaab + "Attestations aggregation on reproposal local context") ~tags:[team; "baker"; "attestation"; "aggregation"; "reproposal"; "local"] ~supports:Protocol.(From_protocol 023) ~uses:(fun _protocol -> [Constant.octez_agnostic_baker]) @@ fun protocol -> - attestations_aggregation_on_reproposal ~remote_mode:false protocol + attestations_aggregation_on_reproposal ~abaab ~remote_mode:false protocol -let attestations_aggregation_on_reproposal_remote_node = +let attestations_aggregation_on_reproposal_remote_node ~abaab = Protocol.register_test ~__FILE__ - ~title:"Attestations aggregation on reproposal remote node" + ~title: + (title_abaab ~abaab "Attestations aggregation on reproposal remote node") ~tags:[team; "baker"; "attestation"; "aggregation"; "reproposal"; "remote"] ~supports:Protocol.(From_protocol 023) ~uses:(fun _protocol -> [Constant.octez_agnostic_baker]) @@ fun protocol -> - attestations_aggregation_on_reproposal ~remote_mode:true protocol + attestations_aggregation_on_reproposal ~abaab ~remote_mode:true protocol -let aggregated_operations_retrival_from_block_content = +let aggregated_operations_retrival_from_block_content ~abaab = Protocol.register_test ~__FILE__ - ~title:"Aggregated operations are retrieved from the block content" + ~title: + (title_abaab + ~abaab + "Aggregated operations are retrieved from the block content") ~tags:[team; "baker"; "aggregation"; "reproposal"; "retrival"] ~supports:Protocol.(From_protocol 023) @@ fun protocol -> @@ -1191,16 +1235,17 @@ let aggregated_operations_retrival_from_block_content = let* parameter_file = Protocol.write_parameter_file ~base:(Right (protocol, None)) - [ - (["allow_tz4_delegate_enable"], `Bool true); - (["aggregate_attestation"], `Bool true); - (* Diminish some constants to activate consensus keys faster *) - (["blocks_per_cycle"], `Int 2); - (["nonce_revelation_threshold"], `Int 1); - (["consensus_rights_delay"], `Int consensus_rights_delay); - (["cache_sampler_state_cycles"], `Int (consensus_rights_delay + 3)); - (["cache_stake_distribution_cycles"], `Int (consensus_rights_delay + 3)); - ] + ([ + (["allow_tz4_delegate_enable"], `Bool true); + (["aggregate_attestation"], `Bool true); + (* Diminish some constants to activate consensus keys faster *) + (["blocks_per_cycle"], `Int 2); + (["nonce_revelation_threshold"], `Int 1); + (["consensus_rights_delay"], `Int consensus_rights_delay); + (["cache_sampler_state_cycles"], `Int (consensus_rights_delay + 3)); + (["cache_stake_distribution_cycles"], `Int (consensus_rights_delay + 3)); + ] + @ abaab_threshold ~abaab ~protocol) in let* node, client = Client.init_with_protocol `Client ~protocol ~parameter_file () @@ -1372,6 +1417,16 @@ let stream_is_refreshed_on_timeout = "The baker did not refresh the streamed RPC after prolonged inactivity \ from the mempool" +let register_with_abaab ~abaab ~protocols = + baker_check_consensus_branch ~abaab protocols ; + force_apply_from_round ~abaab protocols ; + simple_attestations_aggregation_local_context ~abaab protocols ; + simple_attestations_aggregation_remote_node ~abaab protocols ; + prequorum_check_levels ~abaab protocols ; + attestations_aggregation_on_reproposal_local_context ~abaab protocols ; + attestations_aggregation_on_reproposal_remote_node ~abaab protocols ; + aggregated_operations_retrival_from_block_content ~abaab protocols + let register ~protocols = check_node_version_check_bypass_test protocols ; check_node_version_allowed_test protocols ; @@ -1382,13 +1437,7 @@ let register ~protocols = baker_stresstest_apply protocols ; bls_baker_test protocols ; baker_remote_test protocols ; - baker_check_consensus_branch protocols ; - force_apply_from_round protocols ; - simple_attestations_aggregation_local_context protocols ; - simple_attestations_aggregation_remote_node protocols ; - prequorum_check_levels protocols ; - attestations_aggregation_on_reproposal_local_context protocols ; - attestations_aggregation_on_reproposal_remote_node protocols ; - aggregated_operations_retrival_from_block_content protocols ; unable_to_reach_node_mempool protocols ; - stream_is_refreshed_on_timeout protocols + stream_is_refreshed_on_timeout protocols ; + register_with_abaab ~abaab:false ~protocols ; + register_with_abaab ~abaab:true ~protocols -- GitLab From b40b9fc45ec2d698873e458aec1a2aa920cebfe8 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Thu, 9 Oct 2025 16:12:48 +0200 Subject: [PATCH 17/34] Tezt: enable consensus keys for bootstrap in proto param file and delegates too --- .../testnet_experiment_tools.ml | 11 ++- tezt/lib_tezos/client.ml | 12 ++- tezt/lib_tezos/protocol.ml | 98 ++++++++++++++----- tezt/lib_tezos/protocol.mli | 17 +++- tezt/long_tests/dal.ml | 15 ++- tezt/long_tests/mempool_benchmarks.ml | 10 +- tezt/long_tests/pipelining.ml | 10 +- tezt/tests/baker_test.ml | 4 +- tezt/tests/cloud/dal.ml | 21 +++- tezt/tests/signer_test.ml | 2 +- 10 files changed, 156 insertions(+), 44 deletions(-) diff --git a/devtools/testnet_experiment_tools/testnet_experiment_tools.ml b/devtools/testnet_experiment_tools/testnet_experiment_tools.ml index 02ab743f674b..e62fe62e5864 100644 --- a/devtools/testnet_experiment_tools/testnet_experiment_tools.ml +++ b/devtools/testnet_experiment_tools/testnet_experiment_tools.ml @@ -306,7 +306,14 @@ module Local = struct |> Lwt_list.map_s (fun alias -> let* () = Lwt_io.printf "." in let* account_key = Client.show_address ~alias client in - return (account_key, bootstrap_amount_mutez)) + return + ( account_key, + Some + { + Protocol.balance = bootstrap_amount_mutez; + consensus_key = None; + delegate = None; + } )) in let* () = Lwt_io.printf "\n" in let* () = @@ -316,7 +323,7 @@ module Local = struct in let* _filename = Tezt_tezos.Protocol.write_parameter_file - ~bootstrap_accounts + ~overwrite_bootstrap_accounts:(Some bootstrap_accounts) ~base:(Either.Left activation_parameters_filename) ~output_file:output_parameters_filename [] diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index a19fc0542077..5ae53fd0317e 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -3203,7 +3203,16 @@ let get_parameter_file ?additional_bootstrap_accounts ?default_accounts_balance | None -> acc | Some accounts -> List.fold_left - (fun acc x -> (x, default_accounts_balance, revealed) :: acc) + (fun acc x -> + ( x, + Some + { + Protocol.balance = default_accounts_balance; + consensus_key = None; + delegate = None; + }, + revealed ) + :: acc) acc accounts in @@ -3218,6 +3227,7 @@ let get_parameter_file ?additional_bootstrap_accounts ?default_accounts_balance in let* parameter_file = Protocol.write_parameter_file + ~overwrite_bootstrap_accounts:None ~additional_bootstrap_accounts ~base: (Option.fold diff --git a/tezt/lib_tezos/protocol.ml b/tezt/lib_tezos/protocol.ml index 6d0416cb430a..62ef862e3985 100644 --- a/tezt/lib_tezos/protocol.ml +++ b/tezt/lib_tezos/protocol.ml @@ -105,18 +105,29 @@ type bootstrap_smart_rollup = { whitelist : string list option; } +type bootstrap_parameters = { + balance : int option; + consensus_key : Account.key option; + delegate : Account.key option; +} + let default_bootstrap_balance = 4_000_000_000_000 +let default_bootstrap_parameters = + {balance = None; consensus_key = None; delegate = None} + let write_parameter_file : - ?bootstrap_accounts:(Account.key * int option) list -> - ?additional_bootstrap_accounts:(Account.key * int option * bool) list -> + ?overwrite_bootstrap_accounts: + (Account.key * bootstrap_parameters option) list option -> + ?additional_bootstrap_accounts: + (Account.key * bootstrap_parameters option * bool) list -> ?bootstrap_smart_rollups:bootstrap_smart_rollup list -> ?bootstrap_contracts:bootstrap_contract list -> ?output_file:string -> base:(string, t * constants option) Either.t -> parameter_overrides -> string Lwt.t = - fun ?(bootstrap_accounts = default_bootstrap_accounts) + fun ?(overwrite_bootstrap_accounts = Some default_bootstrap_accounts) ?(additional_bootstrap_accounts = []) ?(bootstrap_smart_rollups = []) ?(bootstrap_contracts = []) @@ -137,21 +148,40 @@ let write_parameter_file : if List.mem_assoc ["bootstrap_accounts"] parameter_overrides then parameter_overrides else - let bootstrap_accounts = - List.map - (fun ((account : Account.key), default_balance) -> - `A - [ - `String account.public_key; - `String - (string_of_int - (Option.value - ~default:default_bootstrap_balance - default_balance)); - ]) - bootstrap_accounts - in - (["bootstrap_accounts"], `A bootstrap_accounts) :: parameter_overrides + match overwrite_bootstrap_accounts with + | None -> parameter_overrides + | Some bootstrap_accounts -> + let bootstrap_accounts = + List.map + (fun ((account : Account.key), bootstrap_param) -> + let bootstrap_param = + Option.value + ~default:default_bootstrap_parameters + bootstrap_param + in + `A + ([ + `String account.public_key; + `String + (string_of_int + (Option.value + ~default:default_bootstrap_balance + bootstrap_param.balance)); + ] + @ + match + (bootstrap_param.consensus_key, bootstrap_param.delegate) + with + | None, None -> [] + | Some ck, None -> [`String ck.public_key] + | None, Some dlg -> [`String dlg.public_key_hash] + | Some _, Some _ -> + failwith + "Cannot both set a consensus key and a delegate to a \ + bootstrap account.")) + bootstrap_accounts + in + (["bootstrap_accounts"], `A bootstrap_accounts) :: parameter_overrides in let parameter_overrides = if List.mem_assoc ["bootstrap_smart_rollups"] parameter_overrides then @@ -235,16 +265,30 @@ let write_parameter_file : in let additional_bootstrap_accounts = List.map - (fun ((account : Account.key), default_balance, is_revealed) -> + (fun ((account : Account.key), bootstrap_param, is_revealed) -> + let bootstrap_param = + Option.value ~default:default_bootstrap_parameters bootstrap_param + in `A - [ - `String - (if is_revealed then account.public_key - else account.public_key_hash); - `String - (string_of_int - (Option.value ~default:4000000000000 default_balance)); - ]) + ([ + `String + (if is_revealed then account.public_key + else account.public_key_hash); + `String + (string_of_int + (Option.value + ~default:default_bootstrap_balance + bootstrap_param.balance)); + ] + @ + match (bootstrap_param.consensus_key, bootstrap_param.delegate) with + | None, None -> [] + | Some ck, None -> [`String ck.public_key] + | None, Some dlg -> [`String dlg.public_key_hash] + | Some _, Some _ -> + failwith + "Cannot both set a consensus key and a delegate to a \ + bootstrap account.")) additional_bootstrap_accounts in Ezjsonm.update diff --git a/tezt/lib_tezos/protocol.mli b/tezt/lib_tezos/protocol.mli index 8b3c56c7f263..6ea12cbc1af0 100644 --- a/tezt/lib_tezos/protocol.mli +++ b/tezt/lib_tezos/protocol.mli @@ -114,6 +114,15 @@ type bootstrap_contract = { hash : string option; } +type bootstrap_parameters = { + balance : int option; + consensus_key : Account.key option; + delegate : Account.key option; +} + +(** All fields are set to [None]. A [None] balance will resolve into [default_bootstrap_balance]. *) +val default_bootstrap_parameters : bootstrap_parameters + (** The value is the same as the one in src/proto_alpha/lib_parameters/default_parameters.ml. *) val default_bootstrap_balance : int @@ -126,7 +135,7 @@ val default_bootstrap_balance : int the default parameters of the given protocol are the base parameters. Then, the base parameters are tweaked with: - - [bootstrap_accounts], when given these accounts are used instead of + - [overwrite_bootstrap_accounts], when given these accounts are used instead of [Account.Bootstrap.keys] - [parameters_overrides] - [additional_bootstrap_accounts] is a list of bootstrap accounts to @@ -140,8 +149,10 @@ val default_bootstrap_balance : int a [Temp.file] temporary file "parameters.json" by default. *) val write_parameter_file : - ?bootstrap_accounts:(Account.key * int option) list -> - ?additional_bootstrap_accounts:(Account.key * int option * bool) list -> + ?overwrite_bootstrap_accounts: + (Account.key * bootstrap_parameters option) list option -> + ?additional_bootstrap_accounts: + (Account.key * bootstrap_parameters option * bool) list -> ?bootstrap_smart_rollups:bootstrap_smart_rollup list -> ?bootstrap_contracts:bootstrap_contract list -> ?output_file:string -> diff --git a/tezt/long_tests/dal.ml b/tezt/long_tests/dal.ml index 4b91bbae499b..34aa1206461b 100644 --- a/tezt/long_tests/dal.ml +++ b/tezt/long_tests/dal.ml @@ -62,14 +62,23 @@ let start_l1_node ~protocol ~account ?l1_bootstrap_peer ?dal_bootstrap_peer () = in Protocol.write_parameter_file ~base - ~bootstrap_accounts: + ~overwrite_bootstrap_accounts: (* [bootstrap1] will act as the sole baker so we include it as [bootstrap_accounts]. *) - [(Constant.bootstrap1, None)] + (Some [(Constant.bootstrap1, None)]) ~additional_bootstrap_accounts: (* [bootstrap2] will act as the slot producer so we provide some tez for posting commitments. *) - [(Constant.bootstrap2, Some 1000000, false)] + [ + ( Constant.bootstrap2, + Some + { + Protocol.balance = Some 1000000; + consensus_key = None; + delegate = None; + }, + false ); + ] parameter_overrides in (* Start node with the given protocol *) diff --git a/tezt/long_tests/mempool_benchmarks.ml b/tezt/long_tests/mempool_benchmarks.ml index 761d1659ded6..1e169a4a948a 100644 --- a/tezt/long_tests/mempool_benchmarks.ml +++ b/tezt/long_tests/mempool_benchmarks.ml @@ -131,7 +131,15 @@ let init_node_client_with_protocol ?(sig_algo = "ed25519") in let additional_bootstrap_accounts = List.map - (fun x -> (x, Some 500_000_000_000_000, true)) + (fun x -> + ( x, + Some + { + Protocol.balance = Some 500_000_000_000_000; + consensus_key = None; + delegate = None; + }, + true )) additional_bootstrap_account in let parameters = diff --git a/tezt/long_tests/pipelining.ml b/tezt/long_tests/pipelining.ml index bc14c0c90f8e..05f0d71a338d 100644 --- a/tezt/long_tests/pipelining.ml +++ b/tezt/long_tests/pipelining.ml @@ -191,7 +191,15 @@ let init_node_client_with_protocol number_of_additional_bootstrap protocol = in let additional_bootstrap_accounts = List.map - (fun x -> (x, Some 500_000_000, false)) + (fun x -> + ( x, + Some + { + Protocol.balance = Some 500_000_000; + consensus_key = None; + delegate = None; + }, + false )) additional_bootstrap_account (* Starting with Oxford, bootstrap delegates have part of their balance frozen. To avoid having account with none available balance we don't use diff --git a/tezt/tests/baker_test.ml b/tezt/tests/baker_test.ml index 34d4582e9ee8..fa832d6b56e5 100644 --- a/tezt/tests/baker_test.ml +++ b/tezt/tests/baker_test.ml @@ -160,7 +160,7 @@ let baker_reward_test = let baker_test protocol ~keys = let* parameter_file = Protocol.write_parameter_file - ~bootstrap_accounts:(List.map (fun k -> (k, None)) keys) + ~overwrite_bootstrap_accounts:(Some (List.map (fun k -> (k, None)) keys)) ~base:(Right (protocol, None)) [] in @@ -249,7 +249,7 @@ let bls_baker_test = in let* parameter_file = Protocol.write_parameter_file - ~bootstrap_accounts:(List.map (fun k -> (k, None)) keys) + ~overwrite_bootstrap_accounts:(Some (List.map (fun k -> (k, None)) keys)) ~base:(Right (protocol, None)) [(["allow_tz4_delegate_enable"], `Bool true)] in diff --git a/tezt/tests/cloud/dal.ml b/tezt/tests/cloud/dal.ml index 6875e7f3c303..b3f779324203 100644 --- a/tezt/tests/cloud/dal.ml +++ b/tezt/tests/cloud/dal.ml @@ -690,12 +690,27 @@ let init_sandbox_and_activate_protocol cloud (configuration : configuration) let bootstrap_accounts = List.mapi (fun i Baker_helpers.{delegate; _} -> - (delegate, Some (List.nth stake i * 1_000_000_000_000))) + ( delegate, + Some + { + Protocol.balance = + Some (List.nth stake i * 1_000_000_000_000); + consensus_key = None; + delegate = None; + } )) (List.flatten baker_accounts) in let additional_bootstrap_accounts = List.map - (fun key -> (key, Some 1_000_000_000_000, false)) + (fun key -> + ( key, + Some + { + Protocol.balance = Some 1_000_000_000_000; + consensus_key = None; + delegate = None; + }, + false )) (producer_accounts @ etherlink_rollup_operator_key @ etherlink_batching_operator_keys @ echo_rollup_keys) in @@ -724,7 +739,7 @@ let init_sandbox_and_activate_protocol cloud (configuration : configuration) | None -> [] in Protocol.write_parameter_file - ~bootstrap_accounts + ~overwrite_bootstrap_accounts:(Some bootstrap_accounts) ~additional_bootstrap_accounts ~base overrides diff --git a/tezt/tests/signer_test.ml b/tezt/tests/signer_test.ml index 701696207ce0..92d74890239a 100644 --- a/tezt/tests/signer_test.ml +++ b/tezt/tests/signer_test.ml @@ -62,7 +62,7 @@ let signer_test protocol launch_mode ~keys = let* signer = Signer.init ~launch_mode ~keys () in let* parameter_file = Protocol.write_parameter_file - ~bootstrap_accounts:(List.map (fun k -> (k, None)) keys) + ~overwrite_bootstrap_accounts:(Some (List.map (fun k -> (k, None)) keys)) ~base:(Right (protocol, None)) [] in -- GitLab From ccd6af0adecf0734654bfedc36a20b756d65d35d Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Fri, 10 Oct 2025 15:00:34 +0200 Subject: [PATCH 18/34] Tezt/abaab: reproposal at abaab activation level Shamelessly copied from the previous tests --- tezt/lib_tezos/account.ml | 11 ++ tezt/lib_tezos/account.mli | 12 ++ tezt/tests/baker_test.ml | 339 +++++++++++++++++++++++++++++++++++++ 3 files changed, 362 insertions(+) diff --git a/tezt/lib_tezos/account.ml b/tezt/lib_tezos/account.ml index 7c83d3aa1206..9d365be91f73 100644 --- a/tezt/lib_tezos/account.ml +++ b/tezt/lib_tezos/account.ml @@ -95,6 +95,17 @@ let key_typ : key Check.typ = && String.equal key1.public_key key2.public_key && secret_key_equal key1.secret_key key2.secret_key) +(* The key is not added to a client, it must be manually added later *) +let generate_new_key ~algo ~alias = + let open Tezos_crypto.Signature in + let pkh, pk, sk = generate_key ~algo () in + { + alias; + public_key = Public_key.to_b58check pk; + public_key_hash = Public_key_hash.to_b58check pkh; + secret_key = Unencrypted (Secret_key.to_b58check sk); + } + module Wallet : sig val write : key list -> base_dir:string -> unit end = struct diff --git a/tezt/lib_tezos/account.mli b/tezt/lib_tezos/account.mli index bea8259f1e79..3fe0605e27b7 100644 --- a/tezt/lib_tezos/account.mli +++ b/tezt/lib_tezos/account.mli @@ -86,6 +86,18 @@ val secret_key_typ : secret_key Check.typ faster. *) val write : key list -> base_dir:string -> unit +(** [generate_new_key ~algo ~alias] generates a new key using the given [algo], and + the Tezos crypto library. Even though an [alias] is given, this key is not + registered in a client, and must be registered manually. + Typically, this can be used to generate keys for bootstrap accounts, and include + them in [overwrite_bootstrap_accounts] when calling [Protocol.write_parameter_file]. + At this point it is possible to specify the delegate and consensus keys of an + arbitrary number of bootstrap accounts. + To use these keys in a client and start baking, it is necessary to include them using + [Client.import_secret_key] (which is usually not needed for the default + bootstrap accounts). *) +val generate_new_key : algo:Tezos_crypto.Signature.algo -> alias:string -> key + module Bootstrap : sig (** Standard name for a bootstrap account parameterised by an integer. This alias can be used to name new bootstrap diff --git a/tezt/tests/baker_test.ml b/tezt/tests/baker_test.ml index fa832d6b56e5..28d3a6b73e7c 100644 --- a/tezt/tests/baker_test.ml +++ b/tezt/tests/baker_test.ml @@ -1417,6 +1417,344 @@ let stream_is_refreshed_on_timeout = "The baker did not refresh the streamed RPC after prolonged inactivity \ from the mempool" +let test_reproposal_at_abaab_activation_level = + Protocol.register_test + ~__FILE__ + ~title:"Attestations aggregation on reproposal at abaab activation level" + ~tags: + [ + team; + "baker"; + "attestation"; + "aggregation"; + "reproposal"; + "remote"; + "abaab"; + ] + ~supports:Protocol.(From_protocol 024) + ~uses:(fun _protocol -> [Constant.octez_agnostic_baker]) + @@ fun protocol -> + let consensus_rights_delay = 1 in + let consensus_committee_size = 256 in + let algo = Tezos_crypto.Signature.Bls in + let consensus_key1 = Account.generate_new_key ~algo ~alias:"consensus_key1" in + let consensus_key2 = Account.generate_new_key ~algo ~alias:"consensus_key2" in + let consensus_key3 = Account.generate_new_key ~algo ~alias:"consensus_key3" in + let overwrite_bootstrap_accounts = + Some + [ + ( bootstrap1, + Some + { + Protocol.default_bootstrap_parameters with + consensus_key = Some consensus_key1; + } ); + ( bootstrap2, + Some + { + Protocol.default_bootstrap_parameters with + consensus_key = Some consensus_key2; + } ); + ( bootstrap3, + Some + { + Protocol.default_bootstrap_parameters with + consensus_key = Some consensus_key3; + } ); + (bootstrap4, None); + (bootstrap5, None); + ] + in + let* parameter_file = + Protocol.write_parameter_file + ~overwrite_bootstrap_accounts + ~base:(Right (protocol, None)) + [ + (["allow_tz4_delegate_enable"], `Bool true); + (["aggregate_attestation"], `Bool true); + (* Using custom consensus constants to be able to trigger reproposals *) + (["consensus_committee_size"], `Int consensus_committee_size); + (["consensus_threshold_size"], `Int 70); + (* Diminish some constants to activate consensus keys faster, + and make round durations as small as possible *) + (["minimal_block_delay"], `String "4"); + (["delay_increment_per_round"], `String "0"); + (["blocks_per_cycle"], `Int 2); + (* [blocks_per_cycle] is too short in this testing scenario, + so we increase [tolerated_inactivity_period] *) + (["tolerated_inactivity_period"], `Int 99); + (["nonce_revelation_threshold"], `Int 1); + (["consensus_rights_delay"], `Int consensus_rights_delay); + (["cache_sampler_state_cycles"], `Int (consensus_rights_delay + 3)); + (["cache_stake_distribution_cycles"], `Int (consensus_rights_delay + 3)); + (* We start with 6 bootstrap accounts, 3 with a tz4 consensus key, + a 4th one will activate his later, triggering abaab. *) + (["all_bakers_attest_activation_threshold"; "numerator"], `Int 4); + (["all_bakers_attest_activation_threshold"; "denominator"], `Int 6); + ] + in + let* node, client = + Client.init_with_protocol + `Client + ~additional_revealed_bootstrap_account_count:1 + ~protocol + ~parameter_file + ~timestamp:Now + () + in + let* _ = Node.wait_for_level node 1 in + (* Register the consensus keys in the client *) + let* () = + Client.import_secret_key + client + consensus_key1.secret_key + ~alias:consensus_key1.alias + in + let* () = + Client.import_secret_key + client + consensus_key2.secret_key + ~alias:consensus_key2.alias + in + let* () = + Client.import_secret_key + client + consensus_key3.secret_key + ~alias:consensus_key3.alias + in + (* Check tz4 ratio *) + let* ratio = Client.RPC.call client @@ RPC.get_tz4_baker_number_ratio () in + assert (String.equal (JSON.as_string ratio) "50.00%") ; + (* Setup bootstrap6 as an additional delegate with a tz4 ck *) + let* bootstrap6 = Client.show_address ~alias:"bootstrap6" client in + let* _consensus_key6 = + Client.update_fresh_consensus_key ~algo:"bls" bootstrap6 client + in + let keys = + public_key_hashes + [ + consensus_key1; + consensus_key2; + consensus_key3; + bootstrap1; + bootstrap2; + bootstrap3; + bootstrap4; + ] + in + let* () = Client.bake_for_and_wait ~keys client in + (* Check abaab activation_level + Activation of last tz4 at beginning of cycle 2: level 5 *) + let* ctxt = + Client.RPC.call client @@ RPC.get_chain_block_context_raw ~value_path:[] () + in + let activation_level = + JSON.(ctxt |-> "all_bakers_attest_first_level" |-> "level" |> as_int) + in + assert (activation_level = 5) ; + (* Bootstrap5 does not have enough voting power to progress independently. We + manually inject consensus operations to control the progression of + consensus. *) + Log.info "Launch a baker with bootstrap5" ; + let* _baker = + Agnostic_baker.init + ~delegates:[Constant.bootstrap5.public_key_hash] + node + client + in + let* _ = Client.bake_for_and_wait ~keys ~count:2 client in + let base_level = activation_level - 1 in + let* current_level = + Client.RPC.call client @@ RPC.get_chain_block_helper_current_level () + in + assert (base_level = current_level.level) ; + (* BLS consensus keys are now activated. We feed the node with just enough + consensus operations for the baker to bake a block at [base_level + 1]. *) + let* round = fetch_round client in + let* branch = + Operation.Consensus.get_branch ~attested_level:base_level client + in + let* block_payload_hash = + Operation.Consensus.get_block_payload_hash + ~block:(string_of_int base_level) + client + in + Log.info + "Injecting consensus for bootstrap1 at level %d round %d@." + base_level + round ; + let* () = + Operation.Consensus.( + let* slot = + get_attestation_slot + ~level:base_level + ~protocol + ~consensus_key:consensus_key1 + client + in + let* _ = + preattest_for + ~protocol + ~branch + ~slot + ~level:base_level + ~round + ~block_payload_hash + consensus_key1 + client + in + let* _ = + attest_for + ~protocol + ~branch + ~slot + ~level:base_level + ~round + ~block_payload_hash + consensus_key1 + client + in + unit) + in + let* _ = Node.wait_for_level node (base_level + 1) in + let* () = + check_consensus_operations + ~expected_attestations_committee:[bootstrap1] + ~expected_attestations:[bootstrap5] + client + in + (* The baker running bootstrap5 doesn't have enough voting power to progress + alone. Since we won't attest any block at [base_level + 1], it will keep + baking blocks for [base_level + 1] as round increases. *) + Log.info "Attesting level %d round %d with bootstrap2 & 4" base_level round ; + (* Inject additional attestations for [base_level]. These attestations are + expected to be included in the coming [base_level + 1] proposal. In + particular, bootstrap2 attestation is expected to be incorporated into the + aggregation. Since the baker didn't witnessed a prequorum, it is expected + to bake a fresh proposal. *) + let* () = + Lwt_list.iter_s + Operation.Consensus.( + fun ((consensus_key, companion_key) : Account.key * Account.key option) + -> + let* slot = + get_attestation_slot + ~level:base_level + ~protocol + ~consensus_key + client + in + let* _ = + attest_for + ~protocol + ~branch + ~slot + ~level:base_level + ~round + ~block_payload_hash + ?companion_key + consensus_key + client + in + unit) + [(consensus_key2, None); (bootstrap4, None)] + in + let* _ = Node.wait_for_branch_switch ~level:(base_level + 1) node in + let* () = + check_consensus_operations + ~expected_attestations_committee:[bootstrap1; bootstrap2] + ~expected_attestations:[bootstrap4; bootstrap5] + client + in + Log.info + "Preattesting the latest block at level %d with bootstrap1 & 2" + (base_level + 1) ; + (* We preattest the latest block at level [base_level + 1] with enough voting + power to trigger a prequorum. Consequently, the baker is expected to lock + on the preattested payload and only bake reproposals. *) + let* () = + let* round = fetch_round client in + let* branch = + Operation.Consensus.get_branch ~attested_level:(base_level + 1) client + in + let* block_payload_hash = + Operation.Consensus.get_block_payload_hash client + in + Log.info + "Preattesting level %d round %d with branch %s" + (base_level + 1) + round + branch ; + Lwt_list.iter_s + Operation.Consensus.( + fun (consensus_key : Account.key) -> + let* slot = + get_attestation_slot + ~level:(base_level + 1) + ~protocol + ~consensus_key + client + in + let* _ = + preattest_for + ~protocol + ~branch + ~slot + ~level:(base_level + 1) + ~round + ~block_payload_hash + consensus_key + client + in + unit) + [consensus_key1; consensus_key2; bootstrap4] + in + (* Inject additional attestations for [base_level]. These attestations are + expected to be included in the coming [base_level + 1] reproposals. In + particular, bootstrap3 attestation is expected to be incorporated into the + aggregation. *) + Log.info "Attesting level %d round %d with bootstrap3 & 6" base_level round ; + let* () = + Lwt_list.iter_s + Operation.Consensus.( + fun ((consensus_key, companion_key) : Account.key * Account.key option) + -> + let* slot = + get_attestation_slot + ~level:base_level + ~protocol + ~consensus_key + client + in + let* _ = + attest_for + ~protocol + ~branch + ~slot + ~level:base_level + ~round + ~block_payload_hash + ?companion_key + consensus_key + client + in + unit) + [(consensus_key3, None); (bootstrap6, None)] + in + let* _ = Node.wait_for_branch_switch ~level:(base_level + 1) node in + let* () = + check_consensus_operations + ~expected_attestations_committee:[bootstrap1; bootstrap2; bootstrap3] + ~expected_preattestations_committee:[bootstrap1; bootstrap2] + ~expected_attestations:[bootstrap4; bootstrap5; bootstrap6] + ~expected_preattestations:[bootstrap4; bootstrap5] + client + in + (* Check tz4 ratio *) + let* ratio = Client.RPC.call client @@ RPC.get_tz4_baker_number_ratio () in + assert (String.equal (JSON.as_string ratio) "66.66%") ; + unit + let register_with_abaab ~abaab ~protocols = baker_check_consensus_branch ~abaab protocols ; force_apply_from_round ~abaab protocols ; @@ -1439,5 +1777,6 @@ let register ~protocols = baker_remote_test protocols ; unable_to_reach_node_mempool protocols ; stream_is_refreshed_on_timeout protocols ; + test_reproposal_at_abaab_activation_level protocols ; register_with_abaab ~abaab:false ~protocols ; register_with_abaab ~abaab:true ~protocols -- GitLab From fbe839c4bf3fe2403756487a9bde71a8a3856ca1 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 21 Oct 2025 13:36:08 +0200 Subject: [PATCH 19/34] Test/abaab: test total consensus power --- .../consensus/test_all_bakers_attest.ml | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml index 5cb53cf65611..2dc875057667 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml @@ -569,6 +569,42 @@ let test_activation_with_zero_threshold = --> begin_test ~abaab_activation_levels:[None] ["bootstrap"] --> check_abaab_activation_level ~loc:__LOC__ (Some 0l) +let test_total_consensus_power = + let consensus_rights_delay = + Default_parameters.constants_mainnet.consensus_rights_delay + in + init_constants () + --> set + S.all_bakers_attest_activation_threshold + {numerator = 2; denominator = 1} + --> set + S.consensus_committee_size + Default_parameters.constants_mainnet.consensus_committee_size + --> set + S.consensus_threshold_size + Default_parameters.constants_mainnet.consensus_threshold_size + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ~bootstrap_info_list: + [ + make "baker" ~balance:12_000_000_000L; + make + "future_big_baker" + ~delegate:"baker" + ~balance:12_000_000_000_000L; + ] + [] + --> force_attest_all true + --> set_delegate "future_big_baker" (Some "future_big_baker") + --> stake "future_big_baker" All + --> exec (bake_until (`Cycle (consensus_rights_delay, `Last_level))) + --> force_attest_all false --> attest_with "baker" + (* future big baker cannot attest yet *) + --> + (* We expect the next block to pass the required threshold, + even though future big baker is now active, increasing the total stake *) + next_block + let tests = tests_of_scenarios @@ [ @@ -578,6 +614,7 @@ let tests = ("Test abaab activation level", test_activation_level); ( "Test abaab threshold zero activation", test_activation_with_zero_threshold ); + ("Test abaab total consensus power", test_total_consensus_power); ] let () = -- GitLab From 87038e3eca06ace514c19f8937f70b3fbc89f740 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:47:19 +0100 Subject: [PATCH 20/34] 024_PsD5wVTJ/Proto/tests: init context with initer Porting to proto 024_PsD5wVTJ 0f66a4a6357af1502c545cd61d4e4218c26f20e0 - Proto/tests: init context with initer --- .../lib_protocol/test/helpers/block.ml | 17 ++++++++++++++++- .../lib_protocol/test/helpers/block.mli | 6 +++++- .../lib_protocol/test/helpers/context.ml | 19 +++++++++++-------- .../lib_protocol/test/helpers/context.mli | 7 +++++++ 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/block.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/block.ml index 776ab419edff..0227976f77e1 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/block.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/block.ml @@ -526,7 +526,7 @@ let initial_alpha_context ?(commitments = []) constants in return result -let genesis_with_parameters parameters = +let genesis_with_parameters ?prepare_context parameters = let open Lwt_result_wrap_syntax in let hash = Block_hash.of_b58check_exn @@ -567,6 +567,21 @@ let genesis_with_parameters parameters = in let chain_id = Chain_id.of_block_hash hash in let*@ {context; _} = Main.init chain_id ctxt shell in + let* context = + match prepare_context with + | None -> return context + | Some f -> + let*@ context, _balance_updates, _origination_results = + Init_storage.prepare + context + ~level:0l + ~predecessor_timestamp:Time.Protocol.epoch + ~timestamp:Time.Protocol.epoch + in + let*@ context = f context in + let context = Raw_context.recover context in + return context + in return { hash; diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/block.mli b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/block.mli index 237819d40f60..ba3cebb0aa02 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/block.mli +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/block.mli @@ -163,7 +163,11 @@ val genesis : Parameters.bootstrap_account list -> block tzresult Lwt.t -val genesis_with_parameters : Parameters.t -> block tzresult Lwt.t +val genesis_with_parameters : + ?prepare_context: + (Raw_context.t -> Raw_context.t Environment.Error_monad.tzresult Lwt.t) -> + Parameters.t -> + block tzresult Lwt.t (** [alpha_context accounts] : instantiates an alpha_context with the given constants [] and initializes [accounts] with their diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/context.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/context.ml index fb51ee066ea8..c1506e3544d4 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/context.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/context.ml @@ -31,6 +31,9 @@ open Plugin type t = B of Block.t | I of Incremental.t +type raw_context_modifier = + Raw_context.t -> Raw_context.t Environment.Error_monad.tzresult Lwt.t + (* Begins the construction of a block with the first available baker. Fails if no baker can bake the next block. *) let get_alpha_ctxt c = @@ -837,7 +840,7 @@ let create_bootstrap_accounts_algo_list algo_list = let bootstrap_accounts = Account.make_bootstrap_accounts accounts in (bootstrap_accounts, contracts) -let init_with_constants_gen ?algo tup constants = +let init_with_constants_gen ?algo ?prepare_context tup constants = let open Lwt_result_syntax in let n = tup_n tup in let*? bootstrap_accounts, contracts = create_bootstrap_accounts ?algo n in @@ -847,13 +850,13 @@ let init_with_constants_gen ?algo tup constants = ~bootstrap_accounts constants in - let* blk = Block.genesis_with_parameters parameters in + let* blk = Block.genesis_with_parameters ?prepare_context parameters in return (blk, tup_get tup contracts) -let init_with_constants_n ?algo constants n = - init_with_constants_gen ?algo (TList n) constants +let init_with_constants_n ?algo ?prepare_context constants n = + init_with_constants_gen ?algo ?prepare_context (TList n) constants -let init_with_constants_algo_list constants algo_list = +let init_with_constants_algo_list ?prepare_context constants algo_list = let open Lwt_result_syntax in let n = List.length algo_list in let tup = TList n in @@ -866,19 +869,19 @@ let init_with_constants_algo_list constants algo_list = ~bootstrap_accounts constants in - let* blk = Block.genesis_with_parameters parameters in + let* blk = Block.genesis_with_parameters ?prepare_context parameters in return (blk, tup_get tup contracts) let init_with_constants1 = init_with_constants_gen T1 let init_with_constants2 = init_with_constants_gen T2 -let init_with_parameters_gen tup parameters = +let init_with_parameters_gen ?prepare_context tup parameters = let open Lwt_result_syntax in let n = tup_n tup in let*? bootstrap_accounts, contracts = create_bootstrap_accounts n in let parameters = Parameters.{parameters with bootstrap_accounts} in - let* blk = Block.genesis_with_parameters parameters in + let* blk = Block.genesis_with_parameters ?prepare_context parameters in return (blk, tup_get tup contracts) let init_with_parameters_n params n = init_with_parameters_gen (TList n) params diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/context.mli b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/context.mli index 7d9677cf8d1d..1453b2dec113 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/context.mli +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/context.mli @@ -30,6 +30,9 @@ open Alpha_context type t = B of Block.t | I of Incremental.t +type raw_context_modifier = + Raw_context.t -> Raw_context.t Environment.Error_monad.tzresult Lwt.t + val get_alpha_ctxt : t -> context tzresult Lwt.t val branch : t -> Block_hash.t @@ -454,17 +457,20 @@ val init3 : val init_with_constants_gen : ?algo:Signature.algo -> + ?prepare_context:raw_context_modifier -> (Alpha_context.Contract.t, 'contracts) tup -> Constants.Parametric.t -> (Block.t * 'contracts) tzresult Lwt.t val init_with_constants_n : ?algo:Signature.algo -> + ?prepare_context:raw_context_modifier -> Constants.Parametric.t -> int -> (Block.t * Alpha_context.Contract.t list) tzresult Lwt.t val init_with_constants_algo_list : + ?prepare_context:raw_context_modifier -> Constants.Parametric.t -> Signature.algo option list -> (Block.t * Alpha_context.Contract.t list) tzresult Lwt.t @@ -482,6 +488,7 @@ val init_with_constants2 : accounts. The number of bootstrap accounts, and the structure of the returned contracts, are specified by the [tup] argument. *) val init_with_parameters_gen : + ?prepare_context:raw_context_modifier -> (Alpha_context.Contract.t, 'contracts) tup -> Parameters.t -> (Block.t * 'contracts) tzresult Lwt.t -- GitLab From 58c2abfbeee8855bfc8d0e93199547f73e523ad0 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:47:29 +0100 Subject: [PATCH 21/34] 024_PsD5wVTJ/Proto/tests: can init with cks for bootstraps Porting to proto 024_PsD5wVTJ 02ca1ad4e8297bb3e65c8e7e5131e49e2448f704 - Proto/tests: can init with cks for bootstraps --- .../test/helpers/account_helpers.ml | 15 +- .../test/helpers/scenario_begin.ml | 219 ++++++++++++++++-- .../consensus/test_companion_key.ml | 22 +- .../consensus/test_scenario_attestation.ml | 28 ++- .../integration/test_scenario_slashing.ml | 4 +- 5 files changed, 246 insertions(+), 42 deletions(-) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account_helpers.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account_helpers.ml index b41470f1225c..876ada3befb8 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account_helpers.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account_helpers.ml @@ -70,7 +70,8 @@ let init_account ~name ?delegate ~pkh ~contract ~parameters ?(liquid = Tez.zero) ?(unstaked_finalizable = Unstaked_finalizable.zero) ?(staking_delegator_numerator = Z.zero) ?(staking_delegate_denominator = Z.zero) ?(frozen_rights = CycleMap.empty) - ?(slashed_cycles = []) ?last_seen_activity () = + ?(slashed_cycles = []) ?last_seen_activity ?consensus_key ?companion_key () + = let frozen_deposits = Option.value frozen_deposits ~default:(Frozen_tez.init Tez.zero name name) in @@ -90,8 +91,16 @@ let init_account ~name ?delegate ~pkh ~contract ~parameters ?(liquid = Tez.zero) frozen_rights; slashed_cycles; last_seen_activity; - consensus_keys = CycleMap.empty; - companion_keys = CycleMap.empty; + consensus_keys = + Option.fold + ~none:CycleMap.empty + ~some:(CycleMap.singleton Cycle.root) + consensus_key; + companion_keys = + Option.fold + ~none:CycleMap.empty + ~some:(CycleMap.singleton Cycle.root) + companion_key; } type account_map = account_state String.Map.t diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml index 2b6a9ef33b9f..a1b0fc1a6250 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml @@ -85,24 +85,99 @@ let init_constants ?(default = Test) ?(reward_per_block = 0L) (Protocol.Issuance_bonus_repr.max_bonus_parameter_of_Q_exn Q.zero) else Empty +type algo = Any_algo | Ed25519 | Secp256k1 | P256 | Bls + +let algo_to_algo = function + | Ed25519 -> Some Signature.Ed25519 + | Secp256k1 -> Some Secp256k1 + | P256 -> Some P256 + | Bls -> Some Bls + | Any_algo -> None + +(* None = not set, Some None = set to None (not the same) *) +(* type before applying defaults *) +type bootstrap_info = { + name : string; + algo_opt : algo option; + consensus_key_algo_opt_opt : algo option option; + companion_key_flag_opt : bool option; +} + +(** Used to build bootstrap detailed info. + @param algo defines the algorithm to use for the given bootstrap. + Set to [Any_algo] to choose one randomly. + @param consensus_key [None] means that the bootstrap account does not have a consensus key. + [Some algo] will set a consensus key with the given algo. + @param companion_key is a flag that sets a BLS companion key iff the parameter is set to [true]. +*) +let make ?algo ?consensus_key ?companion_key name = + { + name; + algo_opt = algo; + consensus_key_algo_opt_opt = consensus_key; + companion_key_flag_opt = companion_key; + } + +(* type after applying defaults *) +type bootstrap_full_info = { + name : string; + algo : algo; + consensus_key_algo_opt : algo option; + companion_key_flag : bool; +} + +(* type after creating accounts *) +type bootstrap_accounts = { + name : string; + delegate : Account.t; + consensus_key : Account.t option; + companion_key : Account.t option; +} + (** Initialize the test, given some initial parameters. [algo] defines the algorithm used for the [delegates_name_list]. If not set, a random algorithm is selected for each. To use a different algorithm for each delegate, use [delegates_with_algo] *) -let begin_test ?(delegates_with_algo = []) ?algo ?(burn_rewards = false) +let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) + ?(default_algo = (Any_algo : algo)) + ?(default_consensus_key = (None : algo option)) + ?(default_companion_key = false) ?(burn_rewards = false) ?(force_attest_all = false) ?(force_preattest_all = false) ?(check_finalized_every_block = []) ?(disable_default_checks = false) - delegates_name_list : (constants, t) scenarios = + ?(rng_state = Random.State.make_self_init ()) + (default_bootstrap_name_list : string list) : (constants, t) scenarios = exec (fun (constants : constants) -> let open Lwt_result_syntax in - let delegates_name_algo = - List.map (fun x -> (x, algo)) delegates_name_list - @ List.map (fun (x, algo) -> (x, Some algo)) delegates_with_algo + let make_bootstrap_full (bootstrap_info : bootstrap_info) : + bootstrap_full_info = + { + name = bootstrap_info.name; + algo = Option.value ~default:default_algo bootstrap_info.algo_opt; + consensus_key_algo_opt = + Option.value + ~default:default_consensus_key + bootstrap_info.consensus_key_algo_opt_opt; + companion_key_flag = + Option.value + ~default:default_companion_key + bootstrap_info.companion_key_flag_opt; + } + in + let default_bootstrap name = + make_bootstrap_full + { + name; + algo_opt = None; + consensus_key_algo_opt_opt = None; + companion_key_flag_opt = None; + } in - assert (not @@ List.is_empty delegates_name_algo) ; - let delegates_name_list, delegates_algo_list = - List.split delegates_name_algo + let bootstrap_info_list = + List.map default_bootstrap default_bootstrap_name_list + @ List.map make_bootstrap_full bootstrap_info_list in + (* Please setup at least one bootstrap account *) + assert (not @@ List.is_empty bootstrap_info_list) ; (* Do not disable default checks, unless for a good reason *) let check_finalized_every_block = if disable_default_checks then check_finalized_every_block @@ -110,15 +185,112 @@ let begin_test ?(delegates_with_algo = []) ?algo ?(burn_rewards = false) [check_all_balances; check_misc; check_issuance_rpc] @ check_finalized_every_block in - (* Override threshold value if activate *) - let* block, delegates = - Context.init_with_constants_algo_list constants delegates_algo_list + (* Setup bootstraps and their keys *) + let bootstrap_accounts_list = + List.map + (fun x -> + let delegate = + Account.new_account ?algo:(algo_to_algo x.algo) ~rng_state () + in + let consensus_key = + Option.map + (fun algo -> + Account.new_account ?algo:(algo_to_algo algo) ~rng_state ()) + x.consensus_key_algo_opt + in + let companion_key = + if not x.companion_key_flag then None + else Some (Account.new_account ~algo:Bls ~rng_state ()) + in + {name = x.name; delegate; consensus_key; companion_key}) + bootstrap_info_list + in + (* Setup the bootstrap accounts in the parameters *) + let bootstrap_accounts = + List.map (fun a -> a.delegate) bootstrap_accounts_list + in + let bootstrap_consensus_keys = + List.map + (fun a -> Option.map (fun x -> x.Account.pk) a.consensus_key) + bootstrap_accounts_list + in + let bootstrap_accounts = + Account.make_bootstrap_accounts + ~bootstrap_consensus_keys + bootstrap_accounts + in + let parameters = + Tezos_protocol_024_PsD5wVTJ_parameters.Default_parameters + .parameters_of_constants + ~bootstrap_accounts + constants + in + (* Hack-in the companion keys in the context *) + let set_companion ctxt = + List.fold_left_es + (fun ctxt bootstrap -> + match bootstrap.companion_key with + | None -> return ctxt + | Some ck -> + let key = bootstrap.delegate.Account.pkh in + (* Add the companion key to the global cks storage *) + let*! ctxt = Protocol.Storage.Consensus_keys.add ctxt ck.pkh in + (* Set the companion key for the bootstrap *) + let ck_pk = match ck.pk with Bls x -> x | _ -> assert false in + let ck_pkh = + match ck.pkh with Bls x -> x | _ -> assert false + in + let*! ctxt = + Protocol.Storage.Contract.Companion_key.add + ctxt + (Implicit key) + ck_pk + in + (* Clear the cache: we need to update it with the companion key values. *) + let ctxt = Protocol.Raw_context.Cache.clear ctxt in + (* Update the [Delegate_sampler_state] with the companion key *) + let*! ctxt = + Protocol.Storage.Delegate_sampler_state.fold + ctxt + ~order:`Undefined + ~init:ctxt + ~f:(fun cycle sampler ctxt -> + let sampler = + Protocol.Sampler.map + (fun (x : Protocol.Raw_context.consensus_pk) -> + if Signature.Public_key_hash.equal x.delegate key + then + { + x with + companion_pk = Some ck_pk; + companion_pkh = Some ck_pkh; + } + else x) + sampler + in + Protocol.Storage.Delegate_sampler_state.add + ctxt + cycle + sampler) + in + return ctxt) + ctxt + bootstrap_accounts_list + in + (* Genesis *) + let* block = + Block.genesis_with_parameters ~prepare_context:set_companion parameters in let*? init_level = Context.get_level (B block) in - let*? account_map = - List.fold_left2 - ~when_different_lengths:[Inconsistent_number_of_bootstrap_accounts] - (fun account_map name contract -> + (* init state *) + let account_map = + List.fold_left + (fun account_map bootstrap_account -> + let name = bootstrap_account.name in + let contract = + Protocol.Alpha_context.Contract.Implicit + bootstrap_account.delegate.pkh + in let liquid = Account.default_initial_spendable_balance in let init_staked = Account.default_initial_staked_balance in let frozen_deposits = Frozen_tez.init init_staked name name in @@ -129,6 +301,18 @@ let begin_test ?(delegates_with_algo = []) ?algo ?(burn_rewards = false) Cycle.(root ---> add root constants.consensus_rights_delay) in let pkh = Context.Contract.pkh contract in + let consensus_key = + Option.map + (fun x -> x.Account.pkh) + bootstrap_account.consensus_key + in + let companion_key = + Option.map + (fun x -> + x.Account.pkh |> function Bls x -> x | _ -> assert false + (* by construction, the companion keys built previously are BLS *)) + bootstrap_account.companion_key + in let account = init_account ~name @@ -142,6 +326,8 @@ let begin_test ?(delegates_with_algo = []) ?algo ?(burn_rewards = false) ~frozen_rights ~last_seen_activity: Cycle.(add root constants.consensus_rights_delay) + ?consensus_key + ?companion_key () in let account_map = String.Map.add name account account_map in @@ -152,8 +338,7 @@ let begin_test ?(delegates_with_algo = []) ?algo ?(burn_rewards = false) Log.debug "Initial total balance: %a" Tez.pp total_balance ; account_map) String.Map.empty - delegates_name_list - delegates + bootstrap_accounts_list in let* total_supply = Context.get_total_supply (B block) in let state = diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_companion_key.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_companion_key.ml index ac4b39375aec..f1897310eaf0 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_companion_key.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_companion_key.ml @@ -228,7 +228,7 @@ let test_simple_register_consensus_and_companion_keys = --> begin_test ~force_attest_all:true ~check_finalized_every_block - ~algo:Bls + ~default_algo:Bls bootstrap_accounts --> add_account_with_funds delegate @@ -329,7 +329,7 @@ let test_register_other_accounts_as_ck = --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~algo:Bls + ~default_algo:Bls ~check_finalized_every_block:[(fun _ -> check_all_cks)] ~force_attest_all:true ["delegate"; "victim_1"; "victim_2"] @@ -392,7 +392,7 @@ let test_self_register_as_companion = --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -596,7 +596,7 @@ let test_register_same_key_multiple_times = --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -630,7 +630,7 @@ let test_register_new_key_every_cycle = --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -646,7 +646,7 @@ let test_register_key_end_of_cycle = --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -671,7 +671,7 @@ let test_registration_override = init_constants () --> set S.allow_tz4_delegate_enable true --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -771,7 +771,7 @@ let test_in_registration_table_twice = --> set S.cache_stake_distribution_cycles (consensus_rights_delay + 3) --> set S.cache_sampler_state_cycles (consensus_rights_delay + 3) --> begin_test - ~algo:Bls + ~default_algo:Bls ~force_attest_all:true ~check_finalized_every_block [delegate] @@ -932,7 +932,7 @@ let test_fail_already_registered = let delegate = "delegate" in init_constants () --> set S.allow_tz4_delegate_enable true - --> begin_test ~force_attest_all:true ~algo:Bls [delegate; "ck"] + --> begin_test ~force_attest_all:true ~default_algo:Bls [delegate; "ck"] --> fold_tag (fun kind -> assert_failure @@ -977,7 +977,7 @@ let test_fail_wrong_signer = let delegate = "delegate" in init_constants () --> set S.allow_tz4_delegate_enable true - --> begin_test ~force_attest_all:true ~algo:Bls [delegate; "signer"] + --> begin_test ~force_attest_all:true ~default_algo:Bls [delegate; "signer"] --> add_account ~algo:Bls "ck" --> fold_tag (fun kind -> @@ -1000,7 +1000,7 @@ let test_fail_companion_not_tz4 = let delegate = "delegate" in init_constants () --> set S.allow_tz4_delegate_enable true - --> begin_test ~force_attest_all:true ~algo:Bls [delegate; "signer"] + --> begin_test ~force_attest_all:true ~default_algo:Bls [delegate; "signer"] --> fold_tag (fun algo -> add_account ~algo "ck") [("Ed25519", Ed25519); ("Secp256k1", Secp256k1); ("P256", P256)] diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_scenario_attestation.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_scenario_attestation.ml index 8acb7c97438e..2070d0ba1adb 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_scenario_attestation.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_scenario_attestation.ml @@ -153,7 +153,10 @@ let test_preattest_all = let test_attest_aggreg = init_constants () - --> begin_test ["delegate1"; "delegate2"] ~algo:Bls ~force_attest_all:false + --> begin_test + ["delegate1"; "delegate2"] + ~default_algo:Bls + ~force_attest_all:false --> next_block --> attest_aggreg_with ["delegate1"; "delegate2"] --> next_block @@ -165,7 +168,10 @@ let test_attest_aggreg = let test_preattest_aggreg = init_constants () - --> begin_test ["delegate1"; "delegate2"] ~algo:Bls ~force_preattest_all:false + --> begin_test + ["delegate1"; "delegate2"] + ~default_algo:Bls + ~force_preattest_all:false --> set_baked_round 1 --> next_block --> finalize_payload ~payload_round:0 () --> preattest_aggreg_with ["delegate1"; "delegate2"] @@ -203,13 +209,13 @@ let test_attestation_rewards = |+ Tag "tz4 (solo)" --> begin_test ["delegate"] - ~algo:Bls + ~default_algo:Bls ~disable_default_checks:true ~force_attest_all:true |+ Tag "tz4 (with others)" --> begin_test ["delegate"; "bozo1"; "bozo2"] - ~algo:Bls + ~default_algo:Bls ~disable_default_checks:true ~force_attest_all:true) --> dawn_of_next_cycle @@ -234,7 +240,7 @@ let test_missed_attestations_rewards_tz4 = (* Default checks are disabled because rewards have been changed *) --> begin_test ["delegate"; "bozo1"; "bozo2"] - ~algo:Bls + ~default_algo:Bls ~disable_default_checks:true --> snapshot_balances "init" ["delegate"] --> next_block @@ -285,7 +291,7 @@ let test_forbidden_delegate_tries_to_attest_but_fails_miserably_tz4_edition = init_constants () --> begin_test ["delegate"; "baker"; "attester"] - ~algo:Bls + ~default_algo:Bls ~force_preattest_all:false ~force_attest_all:false --> set_baker ~min_round:1 "baker" @@ -318,13 +324,13 @@ let test_attestations_keep_activation_status = --> (Tag "tz4, attest" --> begin_test accounts - ~algo:Bls + ~default_algo:Bls ~force_preattest_all:false ~force_attest_all:true |+ Tag "tz4, preattest" --> begin_test accounts - ~algo:Bls + ~default_algo:Bls ~force_preattest_all:true ~force_attest_all:false |+ Tag "non tz4, attest" @@ -357,7 +363,8 @@ let test_consensus_threshold = --> set S.consensus_committee_size 1000 --> set S.consensus_threshold_size req_attestations --> begin_test - ~delegates_with_algo:[("delegate_1", Bls); ("delegate_2", Bls)] + ~bootstrap_info_list: + [make "delegate_1" ~algo:Bls; make "delegate_2" ~algo:Bls] ["delegate_3"] (* Genesis cannot be attested *) --> next_block @@ -411,7 +418,8 @@ let test_include_valid_dal_content = --> set S.Dal.number_of_slots number_of_slots --> set S.consensus_rights_delay consensus_rights_delay --> begin_test - ~delegates_with_algo:[("delegate_1", Bls); ("delegate_2", Bls)] + ~bootstrap_info_list: + [make "delegate_1" ~algo:Bls; make "delegate_2" ~algo:Bls] ["delegate_3"] --> next_block (* setup companion keys *) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/test_scenario_slashing.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/test_scenario_slashing.ml index 732937a1290b..7a8e5fcd64e8 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/test_scenario_slashing.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/test_scenario_slashing.ml @@ -197,7 +197,9 @@ let test_delegate_forbidden = init_constants ~blocks_per_cycle:32l () --> (Tag "non tz4" --> begin_test ["delegate"; "bootstrap1"; "bootstrap2"] |+ Tag "tz4" - --> begin_test ~algo:Bls ["delegate"; "bootstrap1"; "bootstrap2"]) + --> begin_test + ~default_algo:Bls + ["delegate"; "bootstrap1"; "bootstrap2"]) --> set_baker "bootstrap1" --> (Tag "Is not forbidden until first denunciation" --> loop 14 (double_bake "delegate") -- GitLab From e15582bb5b7ea19f279dcf4afdbc241ad40da08b Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:47:39 +0100 Subject: [PATCH 22/34] 024_PsD5wVTJ/Proto/tests: simple test init cks Porting to proto 024_PsD5wVTJ 817acfe212cf625d439adb6a53991f407ab88dcd - Proto/tests: simple test init cks --- .../consensus/test_companion_key.ml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_companion_key.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_companion_key.ml index f1897310eaf0..a77ae36540d5 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_companion_key.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_companion_key.ml @@ -208,6 +208,30 @@ let update_key ?proof_signer ?force_no_signer ~kind ~ck_name src = | Companion -> update_companion_key ?proof_signer ?force_no_signer ~ck_name src +let test_init_with_cks_for_bootstraps = + let check_finalized_every_block = [(fun _ -> check_all_cks)] in + init_constants () + --> begin_test + ~check_finalized_every_block + ~force_attest_all:true + ~bootstrap_info_list: + [ + make "no_ck"; + make "with_consensus_key" ~consensus_key:(Some Any_algo); + make "with_companion_key" ~companion_key:true; + make "with_both_tz4" ~consensus_key:(Some Bls) ~companion_key:true; + ] + [] + --> exec_unit check_all_cks + (* Bake a bit, check at each block *) + --> next_block + --> next_block + (* With some DAL, to test the companion key *) + --> exec_state (fun (_block, state) -> + Lwt_result.return {state with State.force_attest_all = false}) + --> attest_aggreg_with ~delegates_with_dal:[("with_both_tz4", Z.of_int 7)] [] + --> next_block + let test_simple_register_consensus_and_companion_keys = let bootstrap_accounts = ["bootstrap1"; "bootstrap2"] in let delegate = "delegate" in @@ -1040,6 +1064,8 @@ let test_batch = let tests = tests_of_scenarios @@ [ + ( "Test bootstrap accounts with initial consensus and companion keys", + test_init_with_cks_for_bootstraps ); ( "Simple update ck for delegate", test_simple_register_consensus_and_companion_keys ); ("Register other accounts as ck", test_register_other_accounts_as_ck); -- GitLab From 1502cd9d7bae04a89f94e6e55bd138630a44a627 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:47:47 +0100 Subject: [PATCH 23/34] 024_PsD5wVTJ/Proto/tests: constants tolerated inactivity Porting to proto 024_PsD5wVTJ 1fbfdb15421f9955abc84c0e9a6a955b53d536fd - Proto/tests: constants tolerated inactivity --- .../lib_protocol/test/helpers/constants_helpers.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/constants_helpers.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/constants_helpers.ml index 08ce382fa9f7..a1697839e4cb 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/constants_helpers.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/constants_helpers.ml @@ -19,6 +19,9 @@ module Set = struct (c : t) = {c with delegate_parameters_activation_delay} + let tolerated_inactivity_period tolerated_inactivity_period (c : t) = + {c with tolerated_inactivity_period} + let blocks_per_cycle blocks_per_cycle (c : t) = {c with blocks_per_cycle} let blocks_per_commitment blocks_per_commitment (c : t) = -- GitLab From 3e82224a1acd101a1e88f4df52cbe3e9940a9899 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:47:55 +0100 Subject: [PATCH 24/34] 024_PsD5wVTJ/Proto/tests: init scenarios with given abaab activ. level Porting to proto 024_PsD5wVTJ 92597e5f3a2f61e6e19884e69d669b5d0013fa5e - Proto/tests: init scenarios with given abaab activ. level --- .../test/helpers/scenario_begin.ml | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml index a1b0fc1a6250..d34809902bdc 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml @@ -145,8 +145,10 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) ?(force_attest_all = false) ?(force_preattest_all = false) ?(check_finalized_every_block = []) ?(disable_default_checks = false) ?(rng_state = Random.State.make_self_init ()) - (default_bootstrap_name_list : string list) : (constants, t) scenarios = - exec (fun (constants : constants) -> + ?(abaab_activation_levels = []) (default_bootstrap_name_list : string list) + : (constants, t) scenarios = + let f abaab_activation_level = + let g constants = let open Lwt_result_syntax in let make_bootstrap_full (bootstrap_info : bootstrap_info) : bootstrap_full_info = @@ -277,10 +279,31 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) ctxt bootstrap_accounts_list in + (* abaab activation level overwrite *) + let abaab_activation_level_overwrite = + match abaab_activation_level with + | None -> return + | Some level -> + fun ctxt -> + let level = + Protocol.Raw_level_repr.of_int32_exn (Int32.of_int level) + in + let cycle_eras = Protocol.Raw_context.cycle_eras ctxt in + let level = + Protocol.Level_repr.level_from_raw ~cycle_eras level + in + let*! ctxt = + Protocol.Storage.All_bakers_attest_activation.add ctxt level + in + return ctxt + in (* Genesis *) - let* block = - Block.genesis_with_parameters ~prepare_context:set_companion parameters + let prepare_context ctxt = + let* ctxt = set_companion ctxt in + let* ctxt = abaab_activation_level_overwrite ctxt in + return ctxt in + let* block = Block.genesis_with_parameters ~prepare_context parameters in let*? init_level = Context.get_level (B block) in (* init state *) let account_map = @@ -375,4 +398,16 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) if not disable_default_checks then check_all_balances () (block, state) else return_unit in - return (block, state)) + return (block, state) + in + exec g + in + match abaab_activation_levels with + | [] -> f None + | _ :: _ -> + fold_tag_f + f + (function + | None -> "abaab initially off" + | Some level -> Format.asprintf "abaab activation at level %d" level) + abaab_activation_levels -- GitLab From 16a05b4e3c3468c6e9476e6b2681f09379d150a3 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:48:03 +0100 Subject: [PATCH 25/34] 024_PsD5wVTJ/Proto/tests: refactor bake_until Porting to proto 024_PsD5wVTJ 6d258c14e36276c0c2a0368da42593222cdd205b - Proto/tests: refactor bake_until --- .../test/helpers/scenario_bake.ml | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_bake.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_bake.ml index 736d0a902f7d..77abbc2a9111 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_bake.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_bake.ml @@ -389,10 +389,11 @@ let rec repeat n f acc = repeat (n - 1) f acc (* adopted from tezt/lib_tezos/client.ml *) -let bake_until_level ~target_level : t -> t tzresult Lwt.t = +let bake_until_level ?(log_message = true) ~target_level : t -> t tzresult Lwt.t + = fun (init_block, init_state) -> let open Lwt_result_syntax in - Log.info "Bake until level %d." target_level ; + if log_message then Log.info "Bake until level %d." target_level ; let current_level = Int32.to_int @@ Block.current_level init_block in if target_level < current_level then Test.fail @@ -407,18 +408,27 @@ let bake_until_level ~target_level : t -> t tzresult Lwt.t = ~error_msg:"Expected level=%R, got %L" ; return (final_block, final_state) -let bake_until ~target_cycle condition : t -> t tzresult Lwt.t = +let bake_until condition : t -> t tzresult Lwt.t = fun (init_block, init_state) -> let blocks_per_cycle = Int32.to_int init_block.constants.blocks_per_cycle in - let target_level, str = + let fs = Format.asprintf in + let target_level, log_str = match condition with - | `New_cycle -> (target_cycle * blocks_per_cycle, "first block") - | `Cycle_end -> (((target_cycle + 1) * blocks_per_cycle) - 1, "last block") - | `Cycle_end_but_one -> - (((target_cycle + 1) * blocks_per_cycle) - 2, "last but one block") + | `Level n -> (n, fs "Bake until level %d" n) + | `Cycle (target_cycle, level_cond) -> + let cycle_offset = target_cycle * blocks_per_cycle in + let level, str = + match level_cond with + | `Level n -> (cycle_offset + n, fs "level position %d" n) + | `First_level -> (cycle_offset, "first level") + | `Last_level -> (cycle_offset + blocks_per_cycle - 1, "last level") + | `Before_last_level -> + (cycle_offset + blocks_per_cycle - 2, "level before last level") + in + (level, fs "Bake until cycle %d, %s (level %d)" target_cycle str level) in - Log.info "Bake until cycle %d (level %d); %s" target_cycle target_level str ; - bake_until_level ~target_level (init_block, init_state) + Log.info "%s" log_str ; + bake_until_level ~log_message:false ~target_level (init_block, init_state) (** Bake until a cycle is reached, using [bake] instead of [Block.bake] *) let bake_until_next_cycle : t -> t tzresult Lwt.t = @@ -427,7 +437,7 @@ let bake_until_next_cycle : t -> t tzresult Lwt.t = Int32.to_int @@ Cycle.to_int32 @@ Cycle.succ @@ Block.current_cycle init_block in - bake_until `New_cycle ~target_cycle:next_cycle (init_block, init_state) + bake_until (`Cycle (next_cycle, `First_level)) (init_block, init_state) (** Bake all the remaining blocks of the current cycle *) let bake_until_dawn_of_next_cycle : t -> t tzresult Lwt.t = @@ -435,7 +445,7 @@ let bake_until_dawn_of_next_cycle : t -> t tzresult Lwt.t = let current_cycle = Int32.to_int @@ Cycle.to_int32 @@ Block.current_cycle init_block in - bake_until `Cycle_end ~target_cycle:current_cycle (init_block, init_state) + bake_until (`Cycle (current_cycle, `Last_level)) (init_block, init_state) let bake_until_next_cycle_end_but_one : t -> t tzresult Lwt.t = fun (init_block, init_state) -> @@ -449,7 +459,7 @@ let bake_until_next_cycle_end_but_one : t -> t tzresult Lwt.t = let target_cycle = if Block.last_block_of_cycle init_block then next_cycle else current_cycle in - bake_until `Cycle_end_but_one ~target_cycle (init_block, init_state) + bake_until (`Cycle (target_cycle, `Before_last_level)) (init_block, init_state) (* ======== Operations ======== *) -- GitLab From 420bf68691d09dc431edbaaa0b380d6d856f0ffa Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:51:48 +0100 Subject: [PATCH 26/34] 024_PsD5wVTJ/Proto/tests: add abaab test file --- manifest/product_octez.ml | 3 +-- .../test/integration/consensus/dune | 3 ++- .../consensus/test_all_bakers_attest.ml | 25 +++++++++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml diff --git a/manifest/product_octez.ml b/manifest/product_octez.ml index 5440894e2fd1..e20c0f327e42 100644 --- a/manifest/product_octez.ml +++ b/manifest/product_octez.ml @@ -6252,8 +6252,7 @@ end = struct ("test_dal_entrapment", N.(number >= 022)); ("test_companion_key", N.(number >= 023)); ("test_scenario_attestation", N.(number >= 023)); - ( "test_all_bakers_attest", - N.(number >= 024 && name_dash <> "024-PsD5wVTJ") ); + ("test_all_bakers_attest", N.(number >= 024)); ] |> conditional_list in diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/dune b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/dune index a5fdb4c61074..169941067c98 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/dune +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/dune @@ -45,7 +45,8 @@ test_aggregate test_dal_entrapment test_companion_key - test_scenario_attestation)) + test_scenario_attestation + test_all_bakers_attest)) (executable (name main) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml new file mode 100644 index 000000000000..ead0a34bdef9 --- /dev/null +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml @@ -0,0 +1,25 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2025 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol ((pre)attestations) + Invocation: dune exec src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_all_bakers_attest.ml + + Subject: Test all bakers attest feature and activation. +*) + +open Scenario + +let tests = tests_of_scenarios @@ [] + +let () = + register_tests + ~__FILE__ + ~tags:["protocol"; "scenario"; "consensus"; "all_bakers_attest"] + tests -- GitLab From 238a46ab2082817300b45604b316e6f787246d87 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:52:11 +0100 Subject: [PATCH 27/34] 024_PsD5wVTJ/Proto/tests: init bootstrap with balance and delegate Porting to proto 024_PsD5wVTJ 43b47c46efca2c45b8c602b6f0b589cef548ab36 - Proto/tests: init bootstrap with balance and delegate --- .../lib_protocol/test/helpers/account.ml | 8 ++ .../lib_protocol/test/helpers/account.mli | 15 +++ .../test/helpers/scenario_begin.ml | 121 +++++++++++++++--- 3 files changed, 126 insertions(+), 18 deletions(-) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account.ml index 83aa119bfe1b..44dc27645001 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account.ml @@ -189,3 +189,11 @@ let rec make_bootstrap_accounts ?(bootstrap_balances = []) ~bootstrap_consensus_keys accounts | [] -> [] + +let make_bootstrap_accounts_packed = + List.map (fun (account, balance, delegate_to, consensus_key) -> + make_bootstrap_account + ?balance:(Option.map Tez.of_mutez_exn balance) + ~delegate_to + ~consensus_key + account) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account.mli b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account.mli index ae7c7a933324..c561267068e6 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account.mli +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/account.mli @@ -118,6 +118,10 @@ val make_bootstrap_account : [bootstrap_balances], [bootstrap_delegations] and [bootstrap_consensus_keys] to create a list of {!Parameters.bootstrap_account} using [make_bootstrap_account]. + The balances, delegations and consensus keys are given in the same order as the + [accounts], and if they get exhausted, the following bootstrap accounts will be + initialized with default values: {!default_initial_full_balance} for the balance, + and [None] for the delegate and consensus key. *) val make_bootstrap_accounts : ?bootstrap_balances:int64 list -> @@ -125,3 +129,14 @@ val make_bootstrap_accounts : ?bootstrap_consensus_keys:Signature.public_key option list -> t list -> Parameters.bootstrap_account list + +(** [make_bootstrap_accounts_packed accounts_packed] creates bootstrap accounts + from each element [(account, balance, delegate_to, consensus_key)] of the given list, + by calling [make_bootstrap_account ~balance ~delegate_to ~consensus_key account]. *) +val make_bootstrap_accounts_packed : + (t + * int64 option + * Signature.public_key_hash option + * Signature.public_key option) + list -> + Parameters.bootstrap_account list diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml index d34809902bdc..f8e238f02366 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml @@ -98,7 +98,9 @@ let algo_to_algo = function (* type before applying defaults *) type bootstrap_info = { name : string; + balance_opt : int64 option; algo_opt : algo option; + delegate_opt : string option; consensus_key_algo_opt_opt : algo option option; companion_key_flag_opt : bool option; } @@ -106,14 +108,26 @@ type bootstrap_info = { (** Used to build bootstrap detailed info. @param algo defines the algorithm to use for the given bootstrap. Set to [Any_algo] to choose one randomly. + @param balance is the initial balance of the bootstrap account. Defaults to + whatever {!Account.make_bootstrap_accounts} sets it to, which should be + {!Default_parameters.Internal_for_tests.bootstrap_balance} + @param delegate is the name of the initial delegate of the account. If set, then the + bootstrap account will not be a self delegate. It cannot be set at the same time as the consensus key. @param consensus_key [None] means that the bootstrap account does not have a consensus key. [Some algo] will set a consensus key with the given algo. @param companion_key is a flag that sets a BLS companion key iff the parameter is set to [true]. *) -let make ?algo ?consensus_key ?companion_key name = +let make ?algo ?balance ?delegate ?consensus_key ?companion_key name = + (match (delegate, consensus_key) with + | Some _, Some _ -> + Stdlib.failwith + "Cannot set both delegate and consensus key for bootstrap account." + | _ -> ()) ; { name; + balance_opt = balance; algo_opt = algo; + delegate_opt = delegate; consensus_key_algo_opt_opt = consensus_key; companion_key_flag_opt = companion_key; } @@ -122,6 +136,8 @@ let make ?algo ?consensus_key ?companion_key name = type bootstrap_full_info = { name : string; algo : algo; + balance_opt : int64 option; + delegate_opt : string option; consensus_key_algo_opt : algo option; companion_key_flag : bool; } @@ -129,11 +145,33 @@ type bootstrap_full_info = { (* type after creating accounts *) type bootstrap_accounts = { name : string; - delegate : Account.t; + balance : int64 option; + account : Account.t; + delegate : string option; consensus_key : Account.t option; companion_key : Account.t option; } +let pp_bootstrap_info fmt (info : bootstrap_accounts) = + let fs = Format.asprintf in + let consensus_key = + Option.map + (fun (x : Account.t) -> + fs " (consensus key: %a)" Signature.Public_key_hash.pp x.pkh) + info.consensus_key + in + let delegate = Option.map (fun x -> fs " (delegate: %s)" x) info.delegate in + Format.fprintf + fmt + "%s: %a%a%a" + info.name + Signature.Public_key_hash.pp + info.account.pkh + Format.(pp_print_option pp_print_string) + consensus_key + Format.(pp_print_option pp_print_string) + delegate + (** Initialize the test, given some initial parameters. [algo] defines the algorithm used for the [delegates_name_list]. If not set, a random algorithm is selected for each. @@ -154,6 +192,8 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) bootstrap_full_info = { name = bootstrap_info.name; + balance_opt = bootstrap_info.balance_opt; + delegate_opt = bootstrap_info.delegate_opt; algo = Option.value ~default:default_algo bootstrap_info.algo_opt; consensus_key_algo_opt = Option.value @@ -169,6 +209,8 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) make_bootstrap_full { name; + balance_opt = None; + delegate_opt = None; algo_opt = None; consensus_key_algo_opt_opt = None; companion_key_flag_opt = None; @@ -191,7 +233,7 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) let bootstrap_accounts_list = List.map (fun x -> - let delegate = + let account = Account.new_account ?algo:(algo_to_algo x.algo) ~rng_state () in let consensus_key = @@ -204,22 +246,43 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) if not x.companion_key_flag then None else Some (Account.new_account ~algo:Bls ~rng_state ()) in - {name = x.name; delegate; consensus_key; companion_key}) + { + name = x.name; + balance = x.balance_opt; + account; + delegate = x.delegate_opt; + consensus_key; + companion_key; + }) bootstrap_info_list in (* Setup the bootstrap accounts in the parameters *) - let bootstrap_accounts = - List.map (fun a -> a.delegate) bootstrap_accounts_list + let get_consensus_key_pk_opt = + fun a -> Option.map (fun x -> x.Account.pk) a.consensus_key + in + let get_delegate_pkh_opt = + fun a -> + Option.map + (fun delegate_name -> + let delegate = + Stdlib.List.find + (fun x -> String.equal x.name delegate_name) + bootstrap_accounts_list + in + delegate.account.pkh) + a.delegate in - let bootstrap_consensus_keys = + let bootstrap_accounts_packed = List.map - (fun a -> Option.map (fun x -> x.Account.pk) a.consensus_key) + (fun a -> + ( a.account, + a.balance, + get_delegate_pkh_opt a, + get_consensus_key_pk_opt a )) bootstrap_accounts_list in let bootstrap_accounts = - Account.make_bootstrap_accounts - ~bootstrap_consensus_keys - bootstrap_accounts + Account.make_bootstrap_accounts_packed bootstrap_accounts_packed in let parameters = Tezos_protocol_024_PsD5wVTJ_parameters.Default_parameters @@ -227,6 +290,10 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) ~bootstrap_accounts constants in + Log.info + "Starting chain with bootstrap accounts:@.%a@." + (Format.pp_print_list ~pp_sep:Format.pp_print_newline pp_bootstrap_info) + bootstrap_accounts_list ; (* Hack-in the companion keys in the context *) let set_companion ctxt = List.fold_left_es @@ -234,7 +301,7 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) match bootstrap.companion_key with | None -> return ctxt | Some ck -> - let key = bootstrap.delegate.Account.pkh in + let key = bootstrap.account.Account.pkh in (* Add the companion key to the global cks storage *) let*! ctxt = Protocol.Storage.Consensus_keys.add ctxt ck.pkh in (* Set the companion key for the bootstrap *) @@ -312,10 +379,24 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) let name = bootstrap_account.name in let contract = Protocol.Alpha_context.Contract.Implicit - bootstrap_account.delegate.pkh + bootstrap_account.account.pkh in - let liquid = Account.default_initial_spendable_balance in - let init_staked = Account.default_initial_staked_balance in + let initial_full = + Option.map Tez.of_mutez bootstrap_account.balance + |> Option.value ~default:Account.default_initial_full_balance + in + let delegate = + Option.value ~default:name bootstrap_account.delegate + in + let self_delegate = String.equal delegate name in + let init_staked = + if not self_delegate then Tez.zero + else + Account.bootstrap_initial_staked_balance + ~constants + ~initial_full_balance:initial_full + in + let liquid = Tez.(initial_full -! init_staked) in let frozen_deposits = Frozen_tez.init init_staked name name in let frozen_rights = List.fold_left @@ -336,19 +417,23 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) (* by construction, the companion keys built previously are BLS *)) bootstrap_account.companion_key in + let last_seen_activity = + if self_delegate then + Some Cycle.(add root constants.consensus_rights_delay) + else None + in let account = init_account ~name ~revealed:true - ~delegate:name + ~delegate ~pkh ~contract ~parameters:default_params ~liquid ~frozen_deposits ~frozen_rights - ~last_seen_activity: - Cycle.(add root constants.consensus_rights_delay) + ?last_seen_activity ?consensus_key ?companion_key () -- GitLab From 6484f33ab3fd045507554dde219b3f9b06006ac9 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:52:20 +0100 Subject: [PATCH 28/34] 024_PsD5wVTJ/Proto/tests: move activity check functions Porting to proto 024_PsD5wVTJ c6a07a14cfcf15702effe72705d7761e4e6f1b9f - Proto/tests: move activity check functions --- .../lib_protocol/test/helpers/log_helpers.ml | 2 ++ .../lib_protocol/test/helpers/scenario.ml | 1 + .../test/helpers/scenario_activity.ml | 22 +++++++++++++++++++ .../integration/test_scenario_deactivation.ml | 14 ------------ 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/log_helpers.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/log_helpers.ml index 2c25ae79e776..c0555a940931 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/log_helpers.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/log_helpers.ml @@ -22,3 +22,5 @@ let batch_color = Log.Color.(BG.green ++ FG.black) let assert_block_color = Log.Color.(BG.blue ++ FG.gray) let tez_color = Log.Color.FG.bright_white + +let check_color = Log.Color.FG.gray diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario.ml index f5c67b616189..b4a7309084a9 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario.ml @@ -16,3 +16,4 @@ include Scenario_begin include Scenario_constants include Scenario_bake include Scenario_attestation +include Scenario_activity diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_activity.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_activity.ml index 30598ac72833..6521245d4eb9 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_activity.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_activity.ml @@ -46,3 +46,25 @@ let update_activity name state current_activity_cycle : State.t = name (update_activity_account state.constants current_activity_cycle) state + +let check_is_active ~loc src_name = + let open Lwt_result_syntax in + Scenario_dsl.exec_unit @@ fun (block, state) -> + Log.info + ~color:Log_helpers.check_color + "Check baker activity: [active] \"%s\"" + src_name ; + let src = State.find_account src_name state in + let* b = Context.Delegate.deactivated (B block) src.pkh in + Assert.is_true ~loc (not b) + +let check_is_not_active ~loc src_name = + let open Lwt_result_syntax in + Scenario_dsl.exec_unit @@ fun (block, state) -> + Log.info + ~color:Log_helpers.check_color + "Check baker activity: [not active] \"%s\"" + src_name ; + let src = State.find_account src_name state in + let* b = Context.Delegate.deactivated (B block) src.pkh in + Assert.is_true ~loc b diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/test_scenario_deactivation.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/test_scenario_deactivation.ml index 54d929accad2..3deb693c0fc4 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/test_scenario_deactivation.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/test_scenario_deactivation.ml @@ -17,20 +17,6 @@ open State_account open Tez_helpers.Ez_tez open Scenario -let check_is_active ~loc src_name = - let open Lwt_result_syntax in - exec_unit @@ fun (block, state) -> - let src = State.find_account src_name state in - let* b = Context.Delegate.deactivated (B block) src.pkh in - Assert.is_true ~loc (not b) - -let check_is_not_active ~loc src_name = - let open Lwt_result_syntax in - exec_unit @@ fun (block, state) -> - let src = State.find_account src_name state in - let* b = Context.Delegate.deactivated (B block) src.pkh in - Assert.is_true ~loc b - let check_rights_aux ~loc ~expect_rights src_name = exec_unit @@ fun (block, state) -> let src = State.find_account src_name state in -- GitLab From 9f2ffd16f8c50ad81342b2ffe88e48196b0204fe Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:52:29 +0100 Subject: [PATCH 29/34] 024_PsD5wVTJ/Proto/tests: add grandgrandparent to state Porting to proto 024_PsD5wVTJ 2ed85d818f8c8c2549e6599e81980a4b9f7a6a39 - Proto/tests: add grandgrandparent to state --- .../lib_protocol/test/helpers/scenario_bake.ml | 1 + .../lib_protocol/test/helpers/scenario_begin.ml | 3 ++- src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/state.ml | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_bake.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_bake.ml index 77abbc2a9111..f9b67e114e36 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_bake.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_bake.ml @@ -369,6 +369,7 @@ let finalize_block_ : t_incr -> t tzresult Lwt.t = check_finalized_current_block = []; previous_metadata = Some metadata; grandparent = previous_block; + grandgrandparent = state.grandparent; } in return (block, state) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml index f8e238f02366..2ff3a91c1381 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml @@ -473,10 +473,11 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) check_finalized_current_block = []; previous_metadata = None; operation_mode = Bake; - (* The grandparent is only used to get the consensus key, so it is + (* The (grand)grandparent(s) is only used to get the consensus key, so it is fine to set it to Genesis here. If needed in the future, an option type would be more appropriate. *) grandparent = block; + grandgrandparent = block; } in let* () = diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/state.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/state.ml index 864da4b9a20d..7b3832cf6caa 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/state.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/state.ml @@ -50,6 +50,7 @@ type t = { previous_metadata : Block.full_metadata option; operation_mode : operation_mode; grandparent : Block.t; + grandgrandparent : Block.t; } (** Expected number of cycles before staking parameters get applied *) -- GitLab From 4a1c0ee847ec64435fa91ccdd6a0de047c3aeca5 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:52:38 +0100 Subject: [PATCH 30/34] 024_PsD5wVTJ/Proto/tests: abaab activation test Porting to proto 024_PsD5wVTJ 2ef4faee689eca6d229fb40b942662f8a0655825 - Proto/tests: abaab activation test --- src/proto_024_PsD5wVTJ/lib_plugin/RPC.ml | 3 + .../test/helpers/constants_helpers.ml | 10 + .../test/helpers/scenario_attestation.ml | 22 +- .../test/helpers/scenario_base.ml | 6 + .../test/helpers/scenario_begin.ml | 20 +- .../consensus/test_all_bakers_attest.ml | 455 +++++++++++++++++- 6 files changed, 499 insertions(+), 17 deletions(-) diff --git a/src/proto_024_PsD5wVTJ/lib_plugin/RPC.ml b/src/proto_024_PsD5wVTJ/lib_plugin/RPC.ml index 615ffcd2537a..b028312e21ca 100644 --- a/src/proto_024_PsD5wVTJ/lib_plugin/RPC.ml +++ b/src/proto_024_PsD5wVTJ/lib_plugin/RPC.ml @@ -4374,6 +4374,9 @@ let consecutive_round_zero ctxt block = let stake_info ctxt block = RPC_context.make_call0 S.stake_info ctxt block () () +let tz4_baker_number_ratio ctxt ?cycle block = + RPC_context.make_call0 S.tz4_baker_number_ratio ctxt block cycle () + let rpc_services = register () ; RPC_directory.merge rpc_services !Registration.patched_services diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/constants_helpers.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/constants_helpers.ml index a1697839e4cb..8439082da1bf 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/constants_helpers.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/constants_helpers.ml @@ -119,6 +119,16 @@ module Set = struct module Dal = struct let number_of_slots number_of_slots (c : t) = dal {c.dal with number_of_slots} c + + let cryptobox_parameters cryptobox_parameters (c : t) = + dal {c.dal with cryptobox_parameters} c + + module Cryptobox_parameters = struct + let number_of_shards number_of_shards (c : t) = + cryptobox_parameters + {c.dal.cryptobox_parameters with number_of_shards} + c + end end let sc_rollup sc_rollup (c : t) = {c with sc_rollup} diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_attestation.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_attestation.ml index 7f012a6bc74b..74cd59379f73 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_attestation.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_attestation.ml @@ -378,14 +378,9 @@ let attest_with_all_ : t -> t tzresult Lwt.t = RPC.Attestation_rights.delegate; consensus_key = _; first_slot = _; - attesting_power; + attesting_power = _; } -> - Tezt.Check.( - (attesting_power > 0) - int - ~__LOC__ - ~error_msg:"Attestation power should be greater than 0, got %L") ; let* is_forbidden = Context.Delegate.is_forbidden (B block) delegate in @@ -603,14 +598,9 @@ let preattest_with_all_ ?payload_round : t_incr -> t_incr tzresult Lwt.t = Plugin.RPC.Attestation_rights.delegate; consensus_key = _; first_slot = _; - attesting_power; + attesting_power = _; } -> - Tezt.Check.( - (attesting_power > 0) - int - ~__LOC__ - ~error_msg:"Attestation power should be greater than 0, got %L") ; let* is_forbidden = Context.Delegate.is_forbidden (I incr) delegate in return (not is_forbidden)) delegates_rights @@ -670,3 +660,11 @@ let preattest_with_all_ ?payload_round : t_incr -> t_incr tzresult Lwt.t = state in return (incr, state) + +let force_attest_all flag = + exec_state (fun (_block, state) -> + Lwt_result.return {state with force_attest_all = flag}) + +let force_preattest_all flag = + exec_state (fun (_block, state) -> + Lwt_result.return {state with force_preattest_all = flag}) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_base.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_base.ml index cc2cfcea4656..239f227d9076 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_base.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_base.ml @@ -68,6 +68,12 @@ let exclude_bakers bakers : (t, t) scenarios = return {state with State.baking_policy = Some (Block.Excluding bakers_pkh)}) +(** Reset the baking policy to [None], i.e the default policy *) +let reset_baking_policy : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_block, state) -> + return {state with State.baking_policy = None}) + let set_payload_round (payload_round : int option) : (t, t) scenarios = let open Lwt_result_syntax in exec_state (fun (_block, state) -> return {state with State.payload_round}) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml index 2ff3a91c1381..366b277e3408 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_begin.ml @@ -85,14 +85,20 @@ let init_constants ?(default = Test) ?(reward_per_block = 0L) (Protocol.Issuance_bonus_repr.max_bonus_parameter_of_Q_exn Q.zero) else Empty -type algo = Any_algo | Ed25519 | Secp256k1 | P256 | Bls +type algo = Any_algo | Ed25519 | Secp256k1 | P256 | Bls | Not_Bls -let algo_to_algo = function +let algo_to_algo ~rng_state = function | Ed25519 -> Some Signature.Ed25519 | Secp256k1 -> Some Secp256k1 | P256 -> Some P256 | Bls -> Some Bls | Any_algo -> None + | Not_Bls -> ( + match Random.State.int rng_state 3 with + | 0 -> Some Signature.Ed25519 + | 1 -> Some Secp256k1 + | 2 -> Some P256 + | _ -> assert false) (* None = not set, Some None = set to None (not the same) *) (* type before applying defaults *) @@ -234,12 +240,18 @@ let begin_test ?(bootstrap_info_list = ([] : bootstrap_info list)) List.map (fun x -> let account = - Account.new_account ?algo:(algo_to_algo x.algo) ~rng_state () + Account.new_account + ?algo:(algo_to_algo ~rng_state x.algo) + ~rng_state + () in let consensus_key = Option.map (fun algo -> - Account.new_account ?algo:(algo_to_algo algo) ~rng_state ()) + Account.new_account + ?algo:(algo_to_algo ~rng_state algo) + ~rng_state + ()) x.consensus_key_algo_opt in let companion_key = diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml index ead0a34bdef9..ef3504aa7900 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml @@ -16,7 +16,460 @@ open Scenario -let tests = tests_of_scenarios @@ [] +(* === Observables === *) +let check_tz4_baker_number_ratio ~loc expected_values = + let open Lwt_result_syntax in + exec_unit (fun (block, _state) -> + Log.info + ~color:Log_helpers.check_color + "Checking tz4 ratio, expecting the following values: [%a]" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt "; ") + Format.pp_print_string) + expected_values ; + let current_cycle = Block.current_cycle block in + List.iteri_es + (fun offset expected -> + let cycle = Protocol.Alpha_context.Cycle.add current_cycle offset in + let* rpc_ratio = + Plugin.RPC.tz4_baker_number_ratio Block.rpc_ctxt ~cycle block + in + Assert.equal + ~loc + String.equal + (Format.asprintf + "Unexpected tz4 baker ratio at cycle %a" + Protocol.Alpha_context.Cycle.pp + cycle) + Format.pp_print_string + expected + rpc_ratio) + expected_values) + +let check_abaab_activation_level ~loc expected_level = + let open Lwt_result_wrap_syntax in + exec_unit (fun (block, _state) -> + Log.info + ~color:Log_helpers.check_color + "Checking activation level for All Bakers Attest, expecting %s" + (match expected_level with + | None -> "none" + | Some level -> Format.asprintf "level %ld" level) ; + let* ctxt = Context.get_alpha_ctxt (B block) in + let (ctxt : Protocol.Raw_context.t) = + Protocol.Alpha_context.Internal_for_tests.to_raw + (ctxt : Protocol.Alpha_context.t) + in + let*@ activation_level = + Protocol.Storage.All_bakers_attest_activation.find ctxt + in + match (activation_level, expected_level) with + | None, None -> return_unit + | Some level, None -> + failwith + "Activation level is set to %a, expected None" + Protocol.Level_repr.pp + level + | None, Some level -> + failwith "Activation level is not set, expected level %ld" level + | Some rpc_level, Some expected -> + let rpc_level = + Protocol.Raw_level_repr.to_int32 rpc_level.Protocol.Level_repr.level + in + Assert.equal_int32 ~loc expected rpc_level) + +let check_all_bakers_attested ~kind = + let open Lwt_result_syntax in + exec_unit (fun (block, state) -> + let get_active_bakers block = + (* gets the stake info of the block's cycle. It includes all active + bakers with a stake. *) + let* _, bakers = Plugin.RPC.stake_info Block.rpc_ctxt block in + return (List.map fst bakers) + in + let* active_bakers = + match kind with + | Attestation -> + if Block.last_block_of_cycle state.State.grandparent then + get_active_bakers state.State.grandgrandparent + else get_active_bakers state.State.grandparent + | Preattestation -> + if Block.last_block_of_cycle block then + get_active_bakers state.State.grandparent + else get_active_bakers block + in + Log.info + ~color:Log_helpers.check_color + "Checking all bakers %s. Expected committee: %a" + (match kind with + | Attestation -> "attested the previous block" + | Preattestation -> "preattested the current block") + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") + Format.pp_print_string) + (List.map + (fun (x : Protocol.Alpha_context.Consensus_key.t) -> + fst (State.find_account_from_pkh x.delegate state)) + active_bakers) ; + let active_bakers_tz4, active_bakers_non_tz4 = + List.partition + (fun (x : Protocol.Alpha_context.Consensus_key.t) -> + match x.consensus_pkh with Bls _ -> true | _ -> false) + active_bakers + in + let* () = + List.iter_es + (fun (x : Protocol.Alpha_context.Consensus_key.t) -> + check_attestation_metadata + ~kind + x.delegate + x.consensus_pkh + (Stdlib.Option.get state.State.previous_metadata) + (block, state)) + active_bakers_non_tz4 + in + check_attestation_aggregate_metadata + ~kind + active_bakers_tz4 + (Stdlib.Option.get state.State.previous_metadata) + (block, state)) + +let check_all_bakers_preattested = + check_all_bakers_attested ~kind:Preattestation + +let check_all_bakers_attested = check_all_bakers_attested ~kind:Attestation + +(* === Tests === *) + +(* The activation level should only be set if more than half of the registered bakers use + BLS to sign. There are four ways to trigger this: + - an existing registered non-tz4 baker registers a tz4 consensus key + - a tz4 account starts baking + - an existing registered non-tz4 baker gets deactivated + - an existing registered non-tz4 bakers unstakes and gets removed from the consensus. + The storage update is done at the end of the cycle. + If a new tz4 starts baking, but then a tz4 also stops baking (different block but same cycle), + then the feature does not activate. + On the activation cycle, there is at least half of the bakers that *actively* sign with a tz4. + On the previous cycle, there is strictly less. In other words, even if there is a delay + to activate a tz4, there is no further delay to activate the feature. + What should be observed is that small bakers can attest after the feature, + but not (or rarely) before + The deactivation case is done in [test_activation_threshold_with_deactivated_baker] +*) +let test_activation_threshold = + let all_bakers_attest_activation_threshold = + Default_parameters.constants_mainnet.all_bakers_attest_activation_threshold + in + let big = 800_000_000_000_000L in + (* 800M tez *) + let small = + Tez_helpers.to_mutez Default_parameters.constants_mainnet.minimal_stake + |> Int64.mul 2L + (* 12000 tez (2 rolls) *) + in + init_constants () + (* Ensures to set value to mainnet default, regardless of [init_constants] default *) + --> set + S.all_bakers_attest_activation_threshold + all_bakers_attest_activation_threshold + (* set consensus_committee_size very low to make small bakers very unlikely + to have any slots before abaab, making observation easier. + It should still be higher than the number of DAL slots. *) + --> set S.consensus_committee_size 20 + (* this requires the number of DAL shards to be reduced *) + --> set S.Dal.Cryptobox_parameters.number_of_shards 10 + (* set threshold size to 0, making attestations not mandatory *) + --> set S.consensus_threshold_size 0 + (* set a reasonable, human friendly number of blocks per cycle *) + --> set S.blocks_per_cycle 10l + (* set inactivity threshold to very high values, so that + they never get deactivated *) + --> set S.tolerated_inactivity_period 99 + (* Begin test: setup different profiles + 7 bakers, 4 non-BLS, 3 BLS, threshold is not reached yet. *) + --> begin_test + ~force_attest_all:true + ~bootstrap_info_list: + [ + (* bakers *) + make "baker_big" ~algo:Not_Bls ~balance:big; + make "baker_small_1" ~algo:Not_Bls ~balance:small; + make "baker_small_2" ~algo:Not_Bls ~balance:small; + make "tz4_baker_big" ~algo:Bls ~balance:big; + make "tz4_baker_small" ~algo:Bls ~balance:small; + make + "non_tz4_with_tz4_ck_baker_big" + ~algo:Not_Bls + ~consensus_key:(Some Bls) + ~balance:big; + make + "tz4_with_non_tz4_ck_baker_big" + ~algo:Bls + ~consensus_key:(Some Not_Bls) + ~balance:big; + (* delegators *) + make + "tz4_delegator_big" + ~algo:Bls + ~balance:big + ~delegate:"non_tz4_with_tz4_ck_baker_big"; + make + "tz4_delegator_small" + ~algo:Bls + ~balance:small + ~delegate:"baker_big"; + ] + [] + (* 3/7 = 42.8571%. We can check for the current cycle and the next two + (because consensus_rights_delay = 2). + Note: the RPC doesn't round to the nearest, it's always flooring. + *) + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["42.85%"; "42.85%"; "42.85%"] + (* And the activation level is not set yet *) + --> check_abaab_activation_level ~loc:__LOC__ None + (* Check also at next cycle *) + --> next_cycle (* Cycle 1, level pos 0: level 10 *) + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* Check that not all bakers attest *) + (* Delegators overdelegate, so they don't count. + Total stake = N = 2_400_036_000 tez * 11/20 + Small staker has a stake of 12_000 tez * 11/20. + Probability that a given small staker has a slot (out of the 20 available slots): + 1 - (1 - 12000/N) ^ 20 = p + Probability that all three small bakers have a slot for the given block at the same + time: p^3 = 10^-12 *) + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_attested + --> (Tag "add and remove tz4" + (* Case where the feature does not activate: we add a tz4, then remove a tz4 in + the same cycle. The feature does not activate. *) + --> add_account ~algo:Bls "consensus_tz4" + --> add_account ~algo:P256 "consensus_non_tz4" + (* First, add a tz4 consensus key to a non tz4 baker *) + --> update_consensus_key ~ck_name:"consensus_tz4" "baker_big" + (* Bake a block, bide your time *) + --> next_block + (* Then, add a non-tz4 consensus key to a tz4 baker *) + --> update_consensus_key ~ck_name:"consensus_non_tz4" "tz4_baker_small" + (* Check RPCs *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* Check RPCs next cycle too *) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* Below are cases where the feature activates *) + |+ (Tag "new tz4 baker" + (* We register a tz4 delegator as a delegate. This should put the ratio + to 50%, which should be enough to trigger the feature *) + --> set_delegate "tz4_delegator_small" (Some "tz4_delegator_small") + --> stake + "tz4_delegator_small" + (Amount (Tez_helpers.of_mutez 10_000_000_000L)) + (* Nothing changed yet *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* next cycle *) + --> next_cycle (* Cycle 2, level pos 0: level 20 *) + (* The distribution for cycle 4 should have been done now, so we should see an activation + at the beginning of cycle 4. + 4 tz4 bakers out of 8 total bakers: 50% *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + (* Wait until activation *) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["50.00%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + |+ Tag "new tz4 consensus key" + --> add_account ~algo:Bls "consensus_tz4" + --> update_consensus_key ~ck_name:"consensus_tz4" "baker_small_1" + (* Nothing changed yet *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* next cycle *) + --> next_cycle (* Cycle 2, level pos 0: level 20 *) + (* The distribution for cycle 4 should have been done now, so we should see an activation + at the beginning of cycle 4. + 4 tz4 bakers out of 7 total bakers: 57.1428% *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "57.14%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + --> (no_tag + (* Wait until activation *) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "57.14%"; "57.14%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["57.14%"; "57.14%"; "57.14%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + |+ Tag "go below threshold but still activate" + --> add_account ~algo:P256 "consensus_non_tz4" + --> update_consensus_key + ~ck_name:"consensus_non_tz4" + "tz4_baker_big" + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "57.14%"; "42.85%"] + (* We still activate *) + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["57.14%"; "42.85%"; "42.85%"] + (* We still activate *) + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l)) + |+ Tag "non-tz4 baker unstake all" + --> unstake "baker_small_2" All + (* Nothing changed yet *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "42.85%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* next cycle *) + --> next_cycle (* Cycle 2, level pos 0: level 20 *) + (* The distribution for cycle 4 should have been done now, so we should see an activation + at the beginning of cycle 4. + 3 tz4 bakers out of 6 total bakers: 50% *) + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "42.85%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + (* Wait until activation *) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["42.85%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l) + --> next_cycle + --> check_tz4_baker_number_ratio + ~loc:__LOC__ + ["50.00%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 40l)) + --> + (* The feature *just* activated. The last baked block can be attested by all + bakers already. *) + force_attest_all true --> force_preattest_all true + --> set_baked_round ~payload_round:0 1 + --> next_block --> check_all_bakers_attested + --> check_all_bakers_preattested + --> exec bake_until_dawn_of_next_cycle + --> check_all_bakers_attested --> check_all_bakers_preattested + --> next_block --> check_all_bakers_attested + --> check_all_bakers_preattested) + +let test_activation_threshold_with_deactivated_baker = + let all_bakers_attest_activation_threshold = + Default_parameters.constants_mainnet.all_bakers_attest_activation_threshold + in + let balance = 4_000_000_000_000L in + (* 4M tez *) + init_constants () + (* Ensures to set value to mainnet default, regardless of [init_constants] default *) + --> set + S.all_bakers_attest_activation_threshold + all_bakers_attest_activation_threshold + (* set consensus_committee_size to the default *) + --> set S.consensus_committee_size 7000 + (* set threshold size to 0, making attestations not mandatory *) + --> set S.consensus_threshold_size 0 + (* set a reasonable, human friendly number of blocks per cycle *) + --> set S.blocks_per_cycle 10l + (* set inactivity threshold very low to wait for a baker to be deactivated *) + --> set S.tolerated_inactivity_period 1 + (* Begin test: setup bootstrap accounts + 3 bakers, 2 non-BLS, 1 BLS, threshold is not reached yet. *) + --> begin_test + ~force_attest_all:true + ~bootstrap_info_list: + [ + (* bakers *) + make "baker_1" ~algo:Not_Bls ~balance; + make "baker_2" ~algo:Not_Bls ~balance; + make "tz4_baker" ~algo:Bls ~balance; + ] + [] + (* 1/3 = 33.3333%. We can check for the current cycle and the next two + (because consensus_rights_delay = 2). + Note: the RPC doesn't round to the nearest, it's always flooring. + *) + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["33.33%"; "33.33%"; "33.33%"] + (* And the activation level is not set yet *) + --> check_abaab_activation_level ~loc:__LOC__ None + (* Check also at next cycle *) + --> next_cycle (* Cycle 1, level pos 0: level 10 *) + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["33.33%"; "33.33%"; "33.33%"] + --> check_abaab_activation_level ~loc:__LOC__ None + (* make "baker_2" inactive. We have to wait for next cycle because + the baker might have attested the first block of the current cycle. *) + --> dawn_of_next_cycle (* Cycle 1, level pos 9: level 19 *) + --> force_attest_all false --> exclude_bakers ["baker_2"] + (* Wait for inactivation, which should be at cycle 4 *) + --> exec (bake_until (`Cycle (4, `First_level))) + (* Cycle 4, level pos 0: level 40 *) + (* "baker_2" neither baked nor attested for two cycles, it should be deactivated. + It should also be the only deactivated baker since the other bakers baked. *) + --> check_is_not_active ~loc:__LOC__ "baker_2" + --> check_is_active ~loc:__LOC__ "baker_1" + --> check_is_active ~loc:__LOC__ "tz4_baker" + (* The distribution for cycle 6 should have been done now, so we should see an activation + at the beginning of cycle 6. + 1 tz4 bakers out of 2 total bakers: 50% *) + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["33.33%"; "33.33%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 60l) + (* Wait until activation *) + --> next_cycle + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["33.33%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 60l) + --> next_cycle + --> check_tz4_baker_number_ratio ~loc:__LOC__ ["50.00%"; "50.00%"; "50.00%"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 60l) + (* Reset state parameters *) + --> force_attest_all true + --> reset_baking_policy + --> + (* The feature *just* activated. The last baked block can be attested by all + bakers already. *) + force_attest_all true --> force_preattest_all true + --> set_baked_round ~payload_round:0 1 + --> next_block --> check_all_bakers_attested --> check_all_bakers_preattested + --> exec bake_until_dawn_of_next_cycle + --> check_all_bakers_attested --> check_all_bakers_preattested --> next_block + --> check_all_bakers_attested --> check_all_bakers_preattested + +let tests = + tests_of_scenarios + @@ [ + ("Test abaab activation threshold", test_activation_threshold); + ( "Test abaab activation threshold when a non BLS baker gets deactivated", + test_activation_threshold_with_deactivated_baker ); + ] let () = register_tests -- GitLab From 441bd88bf6b93b6a64da38c1e9fa481098dc1cf1 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:52:47 +0100 Subject: [PATCH 31/34] 024_PsD5wVTJ/Proto/tests: abaab activation level test Porting to proto 024_PsD5wVTJ 3b26e8e547fa15331acf3657d5113b17ebb73618 - Proto/tests: abaab activation level test --- .../consensus/test_all_bakers_attest.ml | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml index ef3504aa7900..ba979bf23d2a 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml @@ -463,12 +463,111 @@ let test_activation_threshold_with_deactivated_baker = --> check_all_bakers_attested --> check_all_bakers_preattested --> next_block --> check_all_bakers_attested --> check_all_bakers_preattested +let test_activation_level level = + let big = 800_000_000_000_000L in + (* 800M tez *) + let small = + Tez_helpers.to_mutez Default_parameters.constants_mainnet.minimal_stake + |> Int64.mul 2L + (* 12000 tez (2 rolls) *) + in + init_constants () + (* set consensus_committee_size very low to make small bakers very unlikely + to have any slots before abaab, making observation easier. + It should still be higher than the number of DAL slots. *) + --> set S.consensus_committee_size 20 + (* this requires the number of DAL shards to be reduced *) + --> set S.Dal.Cryptobox_parameters.number_of_shards 10 + (* set threshold size to 0, making attestations not mandatory *) + --> set S.consensus_threshold_size 0 + (* set a reasonable, human friendly number of blocks per cycle *) + --> set S.blocks_per_cycle 10l + (* set inactivity period to very high values, so that + bakers never get deactivated *) + --> set S.tolerated_inactivity_period 99 + (* Begin test: setup different profiles + 6 bakers, 2 big, 4 small. *) + --> begin_test + ~force_attest_all:true + ~force_preattest_all:true + ~abaab_activation_levels:[Some level] + ~bootstrap_info_list: + [ + make "big_1" ~algo:Not_Bls ~balance:big; + make "big_2" ~algo:Bls ~balance:big; + make "small_1" ~algo:Not_Bls ~balance:small; + make + "small_2" + ~algo:Not_Bls + ~consensus_key:(Some Bls) + ~balance:small; + make "small_3" ~algo:Bls ~balance:small; + make + "small_4" + ~algo:Bls + ~consensus_key:(Some Not_Bls) + ~balance:small; + ] + [] + (* sanity check *) + --> check_abaab_activation_level ~loc:__LOC__ (Some (Int32.of_int level)) + --> set_baked_round ~payload_round:0 1 + (* next two blocks because cannot attest genesis *) + --> next_block + --> next_block + (* Total stake: N = 1_600_048_000 tez * 11/20 + Probability that a given small staker has a slot (out of the 20 available slots): + 1 - (1 - 12000/N) ^ 20 = p + Probability that all three small bakers have a slot for the given block at the same + time: p^4 = 5.10^-16 *) + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_attested + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_preattested + (* Bake until almost the activation level *) + --> exec (bake_until (`Level (level - 1))) + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_attested + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_preattested + (* Next level: activation level. All bakers can preattest, but attestations + are for the predecessor, which is not under abaab. *) + --> next_block + --> assert_failure + ~loc:__LOC__ + ~expected_error:(fun _ _ -> Lwt_result.return ()) + check_all_bakers_attested + --> check_all_bakers_preattested + (* Next level: abaab is fully activated *) + --> next_block + --> check_all_bakers_attested --> check_all_bakers_preattested + (* We bake a bit, at least a cycle *) + --> loop + 12 + (next_block --> check_all_bakers_attested + --> check_all_bakers_preattested) + +let test_activation_level = + fold_tag_f + test_activation_level + (fun level -> Format.asprintf "level %d" level) + [8; 9; 10; 11; 12] + let tests = tests_of_scenarios @@ [ ("Test abaab activation threshold", test_activation_threshold); ( "Test abaab activation threshold when a non BLS baker gets deactivated", test_activation_threshold_with_deactivated_baker ); + ("Test abaab activation level", test_activation_level); ] let () = -- GitLab From 7f290d3d9f24bac02361e80a4fb049484681ae87 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:52:55 +0100 Subject: [PATCH 32/34] 024_PsD5wVTJ/Proto/tests: attestation tests with abaab Porting to proto 024_PsD5wVTJ c5f9c0845e08605f17bbbef74f49eaa65b26cbb7 - Proto/tests: attestation tests with abaab --- .../lib_protocol/test/helpers/scenario_dsl.ml | 8 +++ .../consensus/test_scenario_attestation.ml | 58 +++++++++++++++---- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_dsl.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_dsl.ml index 042285fa3c46..ddf16c5730bd 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_dsl.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/helpers/scenario_dsl.ml @@ -191,6 +191,14 @@ let fold_tag : let f (s, x) = Tag s --> f x in fold f +let fold_tag_opt : + ('a -> ('b, 'c) scenarios) -> + (string option * 'a) list -> + ('b, 'c) scenarios = + fun f -> + let f (s, x) = (match s with Some s -> Tag s | None -> Empty) --> f x in + fold f + (** [fold_tag_f f tag l] folds [f] over [l], [tag] returns a tag for each element of [l]. Fails on empty list. *) let fold_tag_f : diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_scenario_attestation.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_scenario_attestation.ml index 2070d0ba1adb..f6ff8804eee1 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_scenario_attestation.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_scenario_attestation.ml @@ -97,7 +97,10 @@ let check_aggregated_committee = let test_attest_simple = init_constants () - --> begin_test ["delegate"; "dummy"] ~force_attest_all:false + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate"; "dummy"] + ~force_attest_all:false --> next_block --> attest_with "delegate" --> next_block (* Sanity checks. The positive checks are done every time there is an attestation or a preattestation. *) @@ -106,7 +109,10 @@ let test_attest_simple = let test_preattest_simple = init_constants () - --> begin_test ["delegate"] ~force_preattest_all:false + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate"] + ~force_preattest_all:false --> set_baked_round 1 --> next_block --> finalize_payload ~payload_round:0 () --> preattest_with "delegate" --> finalize_block @@ -116,7 +122,10 @@ let test_preattest_simple = let test_preattest_less_simple = init_constants () - --> begin_test ["delegate1"; "delegate2"] ~force_preattest_all:false + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate1"; "delegate2"] + ~force_preattest_all:false --> set_baked_round 1 --> next_block --> start_payload --> transfer "delegate1" "delegate2" (Amount (Tez_helpers.of_mutez 100L)) --> transfer "delegate2" "delegate1" (Amount (Tez_helpers.of_mutez 99L)) @@ -129,7 +138,10 @@ let test_preattest_less_simple = let test_attest_all = init_constants () - --> begin_test ["delegate1"; "delegate2"] ~force_attest_all:true + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate1"; "delegate2"] + ~force_attest_all:true --> next_block (* This block does not contain attestations; check next. *) --> next_block (* Sanity checks *) @@ -141,7 +153,10 @@ let test_attest_all = let test_preattest_all = init_constants () - --> begin_test ["delegate1"; "delegate2"] ~force_preattest_all:true + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate1"; "delegate2"] + ~force_preattest_all:true --> set_baked_round ~payload_round:0 1 --> next_block (* Sanity checks *) @@ -154,6 +169,7 @@ let test_preattest_all = let test_attest_aggreg = init_constants () --> begin_test + ~abaab_activation_levels:[Some 0; None] ["delegate1"; "delegate2"] ~default_algo:Bls ~force_attest_all:false @@ -169,6 +185,7 @@ let test_attest_aggreg = let test_preattest_aggreg = init_constants () --> begin_test + ~abaab_activation_levels:[Some 0; None] ["delegate1"; "delegate2"] ~default_algo:Bls ~force_preattest_all:false @@ -199,21 +216,25 @@ let init_constants_for_attestation_rewards = } let test_attestation_rewards = + let abaab_activation_levels = [Some 0; None] in init_constants_for_attestation_rewards (* Default checks are disabled because rewards have been changed *) --> (Tag "not tz4" --> begin_test + ~abaab_activation_levels ["delegate"] ~disable_default_checks:true ~force_attest_all:true |+ Tag "tz4 (solo)" --> begin_test + ~abaab_activation_levels ["delegate"] ~default_algo:Bls ~disable_default_checks:true ~force_attest_all:true |+ Tag "tz4 (with others)" --> begin_test + ~abaab_activation_levels ["delegate"; "bozo1"; "bozo2"] ~default_algo:Bls ~disable_default_checks:true @@ -226,7 +247,10 @@ let test_attestation_rewards = let test_missed_attestations_rewards = init_constants_for_attestation_rewards (* Default checks are disabled because rewards have been changed *) - --> begin_test ["delegate"] ~disable_default_checks:true + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ["delegate"] + ~disable_default_checks:true --> snapshot_balances "init" ["delegate"] --> next_block --> (Tag "attest once" --> attest_with "delegate" |+ Tag "no attest" --> noop) @@ -239,6 +263,7 @@ let test_missed_attestations_rewards_tz4 = init_constants_for_attestation_rewards (* Default checks are disabled because rewards have been changed *) --> begin_test + ~abaab_activation_levels:[Some 0; None] ["delegate"; "bozo1"; "bozo2"] ~default_algo:Bls ~disable_default_checks:true @@ -265,6 +290,7 @@ let test_forbidden_delegate_tries_to_attest_but_fails_miserably = in init_constants () --> begin_test + ~abaab_activation_levels:[Some 0; None] ["delegate"; "baker"] ~force_preattest_all:false ~force_attest_all:false @@ -290,6 +316,7 @@ let test_forbidden_delegate_tries_to_attest_but_fails_miserably_tz4_edition = in init_constants () --> begin_test + ~abaab_activation_levels:[Some 0; None] ["delegate"; "baker"; "attester"] ~default_algo:Bls ~force_preattest_all:false @@ -320,27 +347,32 @@ let test_forbidden_delegate_tries_to_attest_but_fails_miserably_tz4_edition = let test_attestations_keep_activation_status = let open Lwt_result_syntax in let accounts = ["delegate"; "baker"; "attester"] in + let abaab_activation_levels = [Some 0; None] in init_constants () --> (Tag "tz4, attest" --> begin_test accounts + ~abaab_activation_levels ~default_algo:Bls ~force_preattest_all:false ~force_attest_all:true |+ Tag "tz4, preattest" --> begin_test accounts + ~abaab_activation_levels ~default_algo:Bls ~force_preattest_all:true ~force_attest_all:false |+ Tag "non tz4, attest" --> begin_test accounts + ~abaab_activation_levels ~force_preattest_all:false ~force_attest_all:true |+ Tag "non tz4, preattest" --> begin_test accounts + ~abaab_activation_levels ~force_preattest_all:true ~force_attest_all:false) --> set_baker ~min_round:1 "baker" @@ -363,6 +395,7 @@ let test_consensus_threshold = --> set S.consensus_committee_size 1000 --> set S.consensus_threshold_size req_attestations --> begin_test + ~abaab_activation_levels:[Some 0; None] ~bootstrap_info_list: [make "delegate_1" ~algo:Bls; make "delegate_2" ~algo:Bls] ["delegate_3"] @@ -379,9 +412,11 @@ let test_consensus_threshold = Assert.expect_error ~loc:__LOC__ errs (function | [ Protocol.Validate_errors.Block.Not_enough_attestations - {required; provided = _}; + {required = _; provided = _}; ] -> - required = Int64.of_int req_attestations + (* TODO ABAAB: check required *) + (* required = Int64.of_int req_attestations *) + true | _ -> false)) next_block --> attest_with "delegate_3" --> next_block @@ -394,9 +429,11 @@ let test_consensus_threshold = Assert.expect_error ~loc:__LOC__ errs (function | [ Protocol.Validate_errors.Block.Not_enough_attestations - {required; provided = _}; + {required = _; provided = _}; ] -> - required = Int64.of_int req_attestations + (* TODO ABAAB: check required *) + (* required = Int64.of_int req_attestations *) + true | _ -> false)) next_block @@ -418,6 +455,7 @@ let test_include_valid_dal_content = --> set S.Dal.number_of_slots number_of_slots --> set S.consensus_rights_delay consensus_rights_delay --> begin_test + ~abaab_activation_levels:[Some 0; None] ~bootstrap_info_list: [make "delegate_1" ~algo:Bls; make "delegate_2" ~algo:Bls] ["delegate_3"] -- GitLab From db5d57c221494c31910df74d93aa2354d204f736 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:53:02 +0100 Subject: [PATCH 33/34] 024_PsD5wVTJ/Proto/tests: abaab zero threshold activation at level 0 Porting to proto 024_PsD5wVTJ 128cbc7cb796aa47103694ba64f4c35b8c3171d2 - Proto/tests: abaab zero threshold activation at level 0 --- .../integration/consensus/test_all_bakers_attest.ml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml index ba979bf23d2a..bcae55e8e01d 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml @@ -561,6 +561,14 @@ let test_activation_level = (fun level -> Format.asprintf "level %d" level) [8; 9; 10; 11; 12] +let test_activation_with_zero_threshold = + init_constants () + --> set + S.all_bakers_attest_activation_threshold + {numerator = 0; denominator = 1} + --> begin_test ~abaab_activation_levels:[None] ["bootstrap"] + --> check_abaab_activation_level ~loc:__LOC__ (Some 0l) + let tests = tests_of_scenarios @@ [ @@ -568,6 +576,8 @@ let tests = ( "Test abaab activation threshold when a non BLS baker gets deactivated", test_activation_threshold_with_deactivated_baker ); ("Test abaab activation level", test_activation_level); + ( "Test abaab threshold zero activation", + test_activation_with_zero_threshold ); ] let () = -- GitLab From f90dbd6f46748c68370f92e65327b5010813d368 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 28 Oct 2025 14:54:14 +0100 Subject: [PATCH 34/34] 024_PsD5wVTJ/Test/abaab: test total consensus power Porting to proto 024_PsD5wVTJ fbe839c4bf3fe2403756487a9bde71a8a3856ca1 - Test/abaab: test total consensus power --- .../consensus/test_all_bakers_attest.ml | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml index bcae55e8e01d..23c60ef16fc5 100644 --- a/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml +++ b/src/proto_024_PsD5wVTJ/lib_protocol/test/integration/consensus/test_all_bakers_attest.ml @@ -569,6 +569,42 @@ let test_activation_with_zero_threshold = --> begin_test ~abaab_activation_levels:[None] ["bootstrap"] --> check_abaab_activation_level ~loc:__LOC__ (Some 0l) +let test_total_consensus_power = + let consensus_rights_delay = + Default_parameters.constants_mainnet.consensus_rights_delay + in + init_constants () + --> set + S.all_bakers_attest_activation_threshold + {numerator = 2; denominator = 1} + --> set + S.consensus_committee_size + Default_parameters.constants_mainnet.consensus_committee_size + --> set + S.consensus_threshold_size + Default_parameters.constants_mainnet.consensus_threshold_size + --> begin_test + ~abaab_activation_levels:[Some 0; None] + ~bootstrap_info_list: + [ + make "baker" ~balance:12_000_000_000L; + make + "future_big_baker" + ~delegate:"baker" + ~balance:12_000_000_000_000L; + ] + [] + --> force_attest_all true + --> set_delegate "future_big_baker" (Some "future_big_baker") + --> stake "future_big_baker" All + --> exec (bake_until (`Cycle (consensus_rights_delay, `Last_level))) + --> force_attest_all false --> attest_with "baker" + (* future big baker cannot attest yet *) + --> + (* We expect the next block to pass the required threshold, + even though future big baker is now active, increasing the total stake *) + next_block + let tests = tests_of_scenarios @@ [ @@ -578,6 +614,7 @@ let tests = ("Test abaab activation level", test_activation_level); ( "Test abaab threshold zero activation", test_activation_with_zero_threshold ); + ("Test abaab total consensus power", test_total_consensus_power); ] let () = -- GitLab