diff --git a/tezt/lib_tezos/node.ml b/tezt/lib_tezos/node.ml index 323ec048e9e6b3db22e3cdff21b8e495fb095223..143f1f6c1b6ec4404247d7fb649dfbe1cde12f92 100644 --- a/tezt/lib_tezos/node.ml +++ b/tezt/lib_tezos/node.ml @@ -383,50 +383,75 @@ module Config_file = struct in JSON.put ("shell", peer_validator) old_config - let sandbox_network_config = + let mk_genesis ~timestamp ~block ~protocol = + `O + [ + ("timestamp", `String timestamp); + ("block", `String block); + ("protocol", `String protocol); + ] + + let mk_genesis_parameters ~genesis_pubkey = + `O [("values", `O [("genesis_pubkey", `String genesis_pubkey)])] + + let sandbox_network_config : JSON.u = `O [ ( "genesis", - `O - [ - ("timestamp", `String "2018-06-30T16:07:32Z"); - ( "block", - `String "BLockGenesisGenesisGenesisGenesisGenesisf79b5d1CoW2" ); - ("protocol", `String Protocol.genesis_hash); - ] ); + mk_genesis + ~timestamp:"2018-06-30T16:07:32Z" + ~block:"BLockGenesisGenesisGenesisGenesisGenesisf79b5d1CoW2" + ~protocol:Protocol.genesis_hash ); ( "genesis_parameters", - `O - [ - ( "values", - `O [("genesis_pubkey", `String Constant.activator.public_key)] - ); - ] ); + mk_genesis_parameters ~genesis_pubkey:Constant.activator.public_key ); ("chain_name", `String "TEZOS"); ("sandboxed_chain_name", `String "SANDBOXED_TEZOS"); ] - let ghostnet_sandbox_network_config = + let ghostnet_sandbox_network_config : JSON.u = `O [ ( "genesis", - `O - [ - ("timestamp", `String "2022-01-25T15:00:00Z"); - ( "block", - `String "BLockGenesisGenesisGenesisGenesisGenesis1db77eJNeJ9" ); - ("protocol", `String Protocol.genesis_hash); - ] ); + mk_genesis + ~timestamp:"2022-01-25T15:00:00Z" + ~block:"BLockGenesisGenesisGenesisGenesisGenesis1db77eJNeJ9" + ~protocol:Protocol.genesis_hash ); ( "genesis_parameters", - `O - [ - ( "values", - `O [("genesis_pubkey", `String Constant.activator.public_key)] - ); - ] ); + mk_genesis_parameters ~genesis_pubkey:Constant.activator.public_key ); ("chain_name", `String "TEZOS"); ("sandboxed_chain_name", `String "SANDBOXED_TEZOS"); ] + (* Copied from Octez_node_config.Config_file *) + let ghostnet_network_config : JSON.u = + `O + [ + ( "genesis", + mk_genesis + ~timestamp:"2022-01-25T15:00:00Z" + ~block:"BLockGenesisGenesisGenesisGenesisGenesis1db77eJNeJ9" + ~protocol:"Ps9mPmXaRzmzk35gbAYNCAw6UXdE2qoABTHbN2oEEc1qM7CwT9P" ); + ( "genesis_parameters", + mk_genesis_parameters + ~genesis_pubkey: + "edpkuYLienS3Xdt5c1vfRX1ibMxQuvfM67ByhJ9nmRYYKGAAoTq1UC" ); + ("chain_name", `String "TEZOS_ITHACANET_2022-01-25T15:00:00Z"); + ("sandboxed_chain_name", `String "SANDBOXED_TEZOS"); + ] + + (* Copied from Octez_node_config.Config_file *) + let mainnet_network_config : JSON.u = + `O + [ + ( "genesis", + mk_genesis + ~timestamp:"2018-06-30T16:07:32Z" + ~block:"BLockGenesisGenesisGenesisGenesisGenesisf79b5d1CoW2" + ~protocol:"Ps9mPmXaRzmzk35gbAYNCAw6UXdE2qoABTHbN2oEEc1qM7CwT9P" ); + ("chain_name", `String "TEZOS_MAINNET"); + ("sandboxed_chain_name", `String "SANDBOXED_TEZOS_MAINNET"); + ] + let put_user_activated_upgrades upgrade_points = JSON.put ( "user_activated_upgrades", @@ -540,7 +565,7 @@ let spawn_snapshot_info ?(json = false) node file = (["snapshot"; "info"] @ (if json then ["--json"] else []) @ [file]) let snapshot_info ?json node file = - spawn_snapshot_info ?json node file |> Process.check + spawn_snapshot_info ?json node file |> Process.check_and_read_stdout let spawn_snapshot_import ?(force = false) ?(no_check = false) ?(reconstruct = false) node file = diff --git a/tezt/lib_tezos/node.mli b/tezt/lib_tezos/node.mli index af011b9ad64353ea225bd5aa338325666baf6f82..b61b474b97832a064de774aeb41360ce8bf341f6 100644 --- a/tezt/lib_tezos/node.mli +++ b/tezt/lib_tezos/node.mli @@ -373,6 +373,14 @@ module Config_file : sig (** Write the configuration file of a node, replacing the existing one. *) val write : t -> JSON.t -> unit Lwt.t + (** Basic network configuration for ghostnet + (genesis, genesis_parameters, chain_name and sandboxed_chain_name *) + val ghostnet_network_config : JSON.u + + (** Basic network configuration for mainnet + (genesis, chain_name and sandboxed_chain_name *) + val mainnet_network_config : JSON.u + (** Update the configuration file of a node. If the node is already running, it needs to be restarted manually. @@ -450,7 +458,7 @@ val spawn_snapshot_export : Process.t (** Run [octez-node snapshot info]. *) -val snapshot_info : ?json:bool -> t -> string -> unit Lwt.t +val snapshot_info : ?json:bool -> t -> string -> string Lwt.t (** Same as [snapshot_info], but do not wait for the process to exit. *) diff --git a/tezt/tests/cloud/layer1.ml b/tezt/tests/cloud/layer1.ml index 3356682790e02415088d3a49f4003817d4f6df38..18a46cf82731bf84fe1b779a924dd994d4c3b04f 100644 --- a/tezt/tests/cloud/layer1.ml +++ b/tezt/tests/cloud/layer1.ml @@ -15,6 +15,11 @@ type baker_account = {pk : string; pkh : string} let add_prometheus_source node cloud agent = Scenarios_helpers.add_prometheus_source ~node cloud agent (Agent.name agent) +let get_snapshot_info_level node snapshot_path = + let* info = Node.snapshot_info node ~json:true snapshot_path in + let json = JSON.parse ~origin:"snapshot_info" info in + Lwt.return JSON.(json |-> "snapshot_header" |-> "level" |> as_int) + module Network = struct include Network @@ -28,6 +33,9 @@ module Network = struct let default_protocol (t : t) = Network.default_protocol (t :> Network.t) let block_time = function `Ghostnet -> 5 | `Mainnet -> 8 + + (** Next protocol for both Mainnet and Ghostnet - needs to be updated manually. *) + let migrate_to _network = Protocol.R022 end let yes_crypto_env = @@ -102,6 +110,32 @@ module Node = struct [Allow_yes_crypto; Force_history_mode_switch] peers + (** [add_migration_offset_to_config node snapshot ~migration_offset ~network] adds an + entry in the configuration file of [node] to trigger a UAU at level [~migration_offset] + to upgrade to the next protocol of [~network]. This entry is is parametrised by the + information obtained from [snapshot]. *) + let add_migration_offset_to_config node snapshot ~migration_offset ~network = + let* level = get_snapshot_info_level node snapshot in + match migration_offset with + | None -> Lwt.return_unit + | Some migration_offset -> + let network_config = + match network with + | `Mainnet -> Node.Config_file.mainnet_network_config + | `Ghostnet -> Node.Config_file.ghostnet_network_config + in + let migration_level = level + migration_offset in + toplog "Add UAU entry for level : %d" migration_level ; + Node.Config_file.update node (fun json -> + JSON.put + ( "network", + JSON.annotate + ~origin:"add_migration_offset_to_config" + network_config ) + json + |> Node.Config_file.update_network_with_user_activated_upgrades + [(migration_level, Network.migrate_to network)]) + (* If trying to only bootstrap the network from a snapshot, you will have errors about missing block metadata, which is likely (I guess?) to be because of data not included in the snapshot. @@ -119,7 +153,8 @@ module Node = struct That's why the bootstrap node first syncs for few levels before being disconnected from the real network. *) - let init_bootstrap_node_from_snapshot ~peers (agent, node) snapshot network = + let init_bootstrap_node_from_snapshot ~peers (agent, node) snapshot network + migration_offset = let* snapshot = ensure_snapshot agent snapshot in let* () = let toplog s = toplog "/!\\ %s /!\\" s in @@ -147,6 +182,9 @@ module Node = struct toplog "Reset node config for private a yes-crypto network" ; let config = isolated_config ~peers ~network ~delay:0 in let* () = Node.config_reset node config in + let* () = + add_migration_offset_to_config node snapshot ~migration_offset ~network + in let arguments = isolated_args peers in let* () = run ~env:yes_crypto_env node arguments in wait_for_ready node @@ -156,10 +194,14 @@ module Node = struct - import the relevant snapshot - run it with yes-crypto enabled and allowed peer lists *) - let init_node_from_snapshot ~delay ~peers ~snapshot ~network (agent, node) = + let init_node_from_snapshot ~delay ~peers ~snapshot ~network ~migration_offset + (agent, node) = let* snapshot = ensure_snapshot agent snapshot in let config = isolated_config ~peers ~network ~delay in let* () = Node.config_init node config in + let* () = + add_migration_offset_to_config node snapshot ~migration_offset ~network + in let* () = Node.snapshot_import ~no_check:true node snapshot in let arguments = isolated_args peers in let* () = run ~env:yes_crypto_env node arguments in @@ -182,10 +224,16 @@ module Node = struct create the associated client, create the yes-wallet. *) - let init_bootstrap_node ~peers ~snapshot ~network (agent, node, name) = + let init_bootstrap_node ~peers ~snapshot ~network ~migration_offset + (agent, node, name) = toplog "Initializing an L1 node (public network): %s" name ; let* () = - init_bootstrap_node_from_snapshot ~peers (agent, node) snapshot network + init_bootstrap_node_from_snapshot + ~peers + (agent, node) + snapshot + network + migration_offset in let* client = client ~node agent in let* yes_wallet = yes_wallet agent in @@ -207,10 +255,16 @@ module Node = struct create the yes-wallet. *) let init_baker_node ?(delay = 0) ~accounts ~peers ~snapshot ~network - (agent, node, name) = + ~migration_offset (agent, node, name) = toplog "Initializing an L1 node (public network): %s" name ; let* () = - init_node_from_snapshot ~delay ~peers ~snapshot ~network (agent, node) + init_node_from_snapshot + ~delay + ~peers + ~snapshot + ~network + ~migration_offset + (agent, node) in let* client = client ~node agent in let* yes_wallet = yes_wallet agent in @@ -225,10 +279,16 @@ module Node = struct Lwt.return client (** Prerequisite: the chain is running (i.e. bakers are baking blocks) *) - let init_stresstest_node ?(delay = 0) ~pkh ~pk ~peers ~snapshot ~network ~tps - (agent, node, name) = + let init_stresstest_node ?(delay = 0) ~pkh ~pk ~peers ~snapshot ~network + ~migration_offset ~tps (agent, node, name) = let* () = - init_node_from_snapshot ~delay ~peers ~snapshot ~network (agent, node) + init_node_from_snapshot + ~delay + ~peers + ~snapshot + ~network + ~migration_offset + (agent, node) in let* client = client ~node agent in let* yes_wallet = yes_wallet agent in @@ -277,6 +337,9 @@ type stresstest_conf = {pkh : string; pk : string; tps : int; seed : int} Default value is 1. Use 0 for disabling delay and have all the bakers to merge their store at the beginning of cycles. + + - [migration_offset]: offset that dictates after how many levels a protocol + upgrade will be performed via a UAU. *) type 'network configuration0 = { stake : int list; @@ -285,6 +348,7 @@ type 'network configuration0 = { snapshot : string; stresstest : stresstest_conf option; maintenance_delay : int; + migration_offset : int option; } type configuration = Network.t configuration0 @@ -332,6 +396,7 @@ let init_baker_i i (configuration : configuration) cloud ~peers ~use_agnostic ~peers ~snapshot:configuration.snapshot ~network:configuration.network + ~migration_offset:configuration.migration_offset (agent, node, name) in let* baker_kind = @@ -368,6 +433,29 @@ let init_baker_i i (configuration : configuration) cloud ~peers ~use_agnostic in let* () = Baker.wait_for_ready baker in toplog "init_baker: %s is ready!" name ; + (* If case of a migration scenario, we also need to start the next protocol baker binary. *) + let* () = + if configuration.migration_offset == None then Lwt.return_unit + else ( + toplog "init_baker_next: Initialize next baker" ; + let name = name ^ "-next" in + let* next_baker = + let protocol = Network.migrate_to configuration.network in + Baker.Agent.init + ~env:yes_crypto_env + ~name + ~delegates: + (List.map (fun ({pkh; _} : baker_account) -> pkh) accounts) + ~protocol + ~client + node + cloud + agent + in + let* () = Baker.wait_for_ready next_baker in + toplog "init_baker_next: %s is ready!" name ; + Lwt.return_unit) + in Lwt.return @@ Classic baker) in Lwt.return @@ -399,6 +487,7 @@ let init_stresstest_i i configuration ~pkh ~pk ~peers (agent, node, name) tps : ~peers ~snapshot:configuration.snapshot ~network:configuration.network + ~migration_offset:configuration.migration_offset (agent, node, name) ~tps in @@ -413,6 +502,7 @@ let init_network ~peers (configuration : configuration) cloud teztale ~peers ~snapshot:configuration.snapshot ~network:configuration.network + ~migration_offset:configuration.migration_offset resources in toplog "init_network: Add a Teztale archiver" ; @@ -897,7 +987,16 @@ let register (module Cli : Scenarios_cli.Layer1) = in let maintenance_delay = Option.value ~default:0 Cli.maintenance_delay in let snapshot = Option.value ~default:"" Cli.snapshot in - {stake; agnostic_bakers; network; stresstest; maintenance_delay; snapshot} + let migration_offset = Cli.migration_offset in + { + stake; + agnostic_bakers; + network; + stresstest; + maintenance_delay; + snapshot; + migration_offset; + } in let vms_conf = Option.map (parse_conf vms_conf_encoding) Cli.vms_config in toplog "Parsing CLI done" ; diff --git a/tezt/tests/cloud/scenarios_cli.ml b/tezt/tests/cloud/scenarios_cli.ml index 0aa43a87ef8f2bda673e11ce6e0518ca3ef04591..7f9987b5c997aaaab6c98bfd782367357e184849 100644 --- a/tezt/tests/cloud/scenarios_cli.ml +++ b/tezt/tests/cloud/scenarios_cli.ml @@ -428,6 +428,8 @@ module type Layer1 = sig val maintenance_delay : int option + val migration_offset : int option + val snapshot : string option val sync : bool @@ -535,6 +537,15 @@ module Layer1 () = struct Default is 1. Use 0 for disabling mainteance delay" () + let migration_offset = + Clap.optional_int + ~section + ~long:"migration-offset" + ~description: + "After how many levels we will perform a UAU to upgrade to the next \ + protocol." + () + let snapshot = Clap.optional_string ~section