Revision 2ca67ca39274572a76a8f299d014d1c25800e147 authored by David Turner on 26 February 2022, 02:18:10 UTC, committed by David Turner on 26 February 2022, 02:20:29 UTC
1 parent 1b4328c
migration.ml
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2020 Metastate AG <hello@metastate.dev> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
let update_config_with_user_activated config_file level protocol =
let user_activated =
Ezjsonm.(
dict
[
( "genesis",
dict
[
("timestamp", string "2018-06-30T16:07:32Z");
( "block",
string "BLockGenesisGenesisGenesisGenesisGenesisf79b5d1CoW2"
);
( "protocol",
string "Ps9mPmXaRzmzk35gbAYNCAw6UXdE2qoABTHbN2oEEc1qM7CwT9P"
);
] );
("chain_name", string "TEZOS_MAINNET");
("old_chain_name", string "TEZOS_BETANET_2018-06-30T16:07:32Z");
("incompatible_chain_name", string "INCOMPATIBLE");
("sandboxed_chain_name", string "SANDBOXED_TEZOS_MAINNET");
( "user_activated_upgrades",
list
dict
[
[("level", int level); ("replacement_protocol", string protocol)];
] );
])
in
let config_json = JSON.parse_file config_file in
let config_json =
Ezjsonm.update
(JSON.unannotate config_json)
["network"]
(Some user_activated)
in
with_open_out config_file (fun chan ->
Ezjsonm.value_to_channel ~minify:false chan config_json)
let rec bake_with_foundation ?(foundation_index = [1; 2; 3; 4; 5; 6; 7; 8])
client =
let len = List.length foundation_index in
if len = 0 then Test.fail "No foundation contract could bake"
else
let index = Random.int len in
let foundation = List.nth foundation_index index in
let proc =
Client.spawn_bake_for
~keys:["foundation" ^ string_of_int foundation]
client
in
let* res = Process.wait proc in
if res != Unix.WEXITED 0 then
let* has_correct_error =
Lwt_stream.find
(fun stderr_bake ->
stderr_bake =~ rex "No\\sslot\\sfound\\sat\\slevel\\s[0-9]+")
(Lwt_io.read_lines (Process.stderr proc))
in
if Option.is_some has_correct_error then
let foundation_index =
List.filter (( <> ) foundation) foundation_index
in
bake_with_foundation ~foundation_index client
else unit
else unit
let create_yes_wallet () =
let yes_wallet = Temp.dir "yes-wallet" in
let open Yes_wallet_lib in
json_to_file
(pkh_list_json alias_pkh_pk_list)
(yes_wallet // "public_key_hashs") ;
json_to_file (pk_list_json alias_pkh_pk_list) (yes_wallet // "public_keys") ;
json_to_file (sk_list_json alias_pkh_pk_list) (yes_wallet // "secret_keys") ;
yes_wallet
(* This test checks the migration of a protocol with a context imported from a
snapshot. See the tezos online documentation to have an in-depth explanation
of that test and how to use it. The documentation can be found at this
address: https://tezos.gitlab.io/developer/proposal_testing.html *)
let migration ?yes_node_path ?yes_wallet context protocol =
Test.register
~__FILE__
~title:"migration test"
~tags:["node"; "activate"; "user_activated"; "protocol"; "migration"]
@@ fun () ->
Log.info
"Starting migration test of protocol %s in context %s"
protocol
context ;
Log.info "Copying context into a temporary directory" ;
let data_dir = Temp.dir "tezos-node-test" in
let* () = Process.run "cp" ["-R"; context ^ "/."; data_dir] in
let* node =
Node.init ~rpc_port:19731 ~net_port:18731 ~data_dir [Connections 0]
in
let endpoint = Client.(Node node) in
let* client = Client.init ~endpoint () in
let* json = RPC.get_current_level ~endpoint client in
let level = JSON.(json |-> "level" |> as_int) in
let* () = Node.terminate node in
Log.info "Updating node config with user_activated_upgrade" ;
let migration_level = level + 1 in
update_config_with_user_activated
(data_dir ^ "/config.json")
migration_level
protocol ;
let node =
Node.create ?path:yes_node_path ~rpc_port:19731 ~net_port:18731 ~data_dir []
in
let endpoint = Client.(Node node) in
let* () = Node.run node [Connections 0] in
let* () = Node.wait_for_ready node in
Log.info "Creating yes-wallet dir" ;
let* base_dir =
match yes_wallet with
| Some yes_wallet ->
let base_dir = Temp.dir "client" in
let* () = Process.run "cp" ["-R"; yes_wallet ^ "/."; base_dir] in
Lwt.return base_dir
| None -> Lwt.return @@ create_yes_wallet ()
in
let client = Client.create ~base_dir ~endpoint () in
Log.info "Bake and wait until migration is finished" ;
let* () = bake_with_foundation client in
let* _until_mig = Node.wait_for_level node migration_level in
let* levels_in_current_cycle = RPC.get_levels_in_current_cycle client in
let last_block_of_cycle =
JSON.(levels_in_current_cycle |-> "last" |> as_int)
in
let* prev_level = RPC.get_current_level client in
let prev_cycle = JSON.(prev_level |-> "cycle" |> as_int) in
Log.info "Bake until new cycle" ;
let* () =
repeat
(last_block_of_cycle - migration_level + 1)
(fun () -> bake_with_foundation client)
in
let* _until_end_of_cycle = Node.wait_for_level node last_block_of_cycle in
let* after_level = RPC.get_current_level client in
let after_cycle = JSON.(after_level |-> "cycle" |> as_int) in
if prev_cycle + 1 <> after_cycle then
Test.fail
"The cycle of current level is %d where it was expected to be %d "
prev_cycle
after_cycle
else unit
let protocol =
let default = Protocol.(hash Alpha) in
Option.value ~default (Sys.getenv_opt "TEZT_MIGRATION_TEST_PROTOCOL")
let context =
let default =
let home = Sys.getenv "HOME" in
home ^ "/tezos-node-test"
in
Option.value ~default (Sys.getenv_opt "TEZT_MIGRATION_TEST_CONTEXT")
let register () = migration context protocol
Computing file changes ...