diff --git a/michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz b/michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz new file mode 100644 index 0000000000000000000000000000000000000000..823a83c0b057e950500a118ca1354997cb32ab4b --- /dev/null +++ b/michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz @@ -0,0 +1,17 @@ +parameter (pair (pair bytes nat) (contract (ticket bytes)) ); +storage unit; +code + { + UNPAIR; + UNPAIR; + UNPAIR; + TICKET; + ASSERT_SOME; + PUSH mutez 0; + SWAP; + TRANSFER_TOKENS; + NIL operation; + SWAP; + CONS; + PAIR + } diff --git a/tezt/lib_tezos/node.ml b/tezt/lib_tezos/node.ml index ad05e4cab5d0fb94d3cc55bf6897858763947beb..af9ce7ead7dea977f91ac34884a8a594492efadd 100644 --- a/tezt/lib_tezos/node.ml +++ b/tezt/lib_tezos/node.ml @@ -804,7 +804,13 @@ let do_runlike_command ?(on_terminate = fun _ -> ()) ?event_level arguments ~on_terminate -let run ?on_terminate ?event_level ?event_sections_levels node arguments = +let run ?patch_config ?on_terminate ?event_level ?event_sections_levels node + arguments = + let () = + match patch_config with + | None -> () + | Some patch -> Config_file.update node patch + in let arguments = runlike_command_arguments node "run" arguments in do_runlike_command ?on_terminate @@ -852,18 +858,15 @@ let init ?runner ?path ?name ?color ?data_dir ?event_pipe ?net_port in let* () = identity_generate node in let* () = config_init node [] in - let () = - match patch_config with - | None -> () - | Some patch -> Config_file.update node patch - in let* () = match snapshot with | Some (file, reconstruct) -> snapshot_import ~reconstruct node file | None -> unit in let argument = if single_process then [Singleprocess] else [] in - let* () = run ?event_level ?event_sections_levels node argument in + let* () = + run ?patch_config ?event_level ?event_sections_levels node argument + in let* () = wait_for_ready node in return node diff --git a/tezt/lib_tezos/node.mli b/tezt/lib_tezos/node.mli index d74fc04c90edffb65e5aa281e2948dbd5c082a06..52413d022252eb0e2c8d71cd833af223189ab1d8 100644 --- a/tezt/lib_tezos/node.mli +++ b/tezt/lib_tezos/node.mli @@ -393,6 +393,7 @@ val spawn_reconstruct : t -> Process.t for a more precise semantic. *) val run : + ?patch_config:(JSON.t -> JSON.t) -> ?on_terminate:(Unix.process_status -> unit) -> ?event_level:Daemon.Level.default_level -> ?event_sections_levels:(string * Daemon.Level.level) list -> diff --git a/tezt/tests/expected/contract_typecheck_regression.ml/Alpha- Tc mini_scenarios-sc_rollup_mint_and_forward.out b/tezt/tests/expected/contract_typecheck_regression.ml/Alpha- Tc mini_scenarios-sc_rollup_mint_and_forward.out new file mode 100644 index 0000000000000000000000000000000000000000..bfaf02b71524747aad44201908bd9a5c75622128 --- /dev/null +++ b/tezt/tests/expected/contract_typecheck_regression.ml/Alpha- Tc mini_scenarios-sc_rollup_mint_and_forward.out @@ -0,0 +1,29 @@ + +./octez-client --protocol ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK --mode mockup --no-base-dir-warnings typecheck script michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz --details +Well typed +Gas remaining: 1039990.860 units remaining +{ parameter (pair (pair bytes nat) (contract (ticket bytes))) ; + storage unit ; + code { UNPAIR + /* [ pair (pair bytes nat) (contract (ticket bytes)) : unit ] */ ; + UNPAIR + /* [ pair bytes nat : contract (ticket bytes) : unit ] */ ; + UNPAIR + /* [ bytes : nat : contract (ticket bytes) : unit ] */ ; + TICKET + /* [ option (ticket bytes) : contract (ticket bytes) : unit ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : ticket bytes : contract (ticket bytes) : unit ] */ ; + SWAP + /* [ ticket bytes : mutez : contract (ticket bytes) : unit ] */ ; + TRANSFER_TOKENS + /* [ operation : unit ] */ ; + NIL operation + /* [ list operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } diff --git a/tezt/tests/expected/contract_typecheck_regression.ml/Lima- Tc mini_scenarios-sc_rollup_mint_and_forward.out b/tezt/tests/expected/contract_typecheck_regression.ml/Lima- Tc mini_scenarios-sc_rollup_mint_and_forward.out new file mode 100644 index 0000000000000000000000000000000000000000..52f598b4dae4e0fa21bd1754f30c5f4d54548354 --- /dev/null +++ b/tezt/tests/expected/contract_typecheck_regression.ml/Lima- Tc mini_scenarios-sc_rollup_mint_and_forward.out @@ -0,0 +1,29 @@ + +./octez-client --protocol PtLimaPtLMwfNinJi9rCfDPWea8dFgTZ1MeJ9f1m2SRic6ayiwW --mode mockup --no-base-dir-warnings typecheck script michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz --details +Well typed +Gas remaining: 1039990.860 units remaining +{ parameter (pair (pair bytes nat) (contract (ticket bytes))) ; + storage unit ; + code { UNPAIR + /* [ pair (pair bytes nat) (contract (ticket bytes)) : unit ] */ ; + UNPAIR + /* [ pair bytes nat : contract (ticket bytes) : unit ] */ ; + UNPAIR + /* [ bytes : nat : contract (ticket bytes) : unit ] */ ; + TICKET + /* [ option (ticket bytes) : contract (ticket bytes) : unit ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : ticket bytes : contract (ticket bytes) : unit ] */ ; + SWAP + /* [ ticket bytes : mutez : contract (ticket bytes) : unit ] */ ; + TRANSFER_TOKENS + /* [ operation : unit ] */ ; + NIL operation + /* [ list operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } diff --git a/tezt/tests/expected/contract_typecheck_regression.ml/Mumbai- Tc mini_scenarios-sc_rollup_mint_and_forward.out b/tezt/tests/expected/contract_typecheck_regression.ml/Mumbai- Tc mini_scenarios-sc_rollup_mint_and_forward.out new file mode 100644 index 0000000000000000000000000000000000000000..9137b27d1d0763ead61526d00f8e96d9849a7af9 --- /dev/null +++ b/tezt/tests/expected/contract_typecheck_regression.ml/Mumbai- Tc mini_scenarios-sc_rollup_mint_and_forward.out @@ -0,0 +1,29 @@ + +./octez-client --protocol PtMumbai2TmsJHNGRkD8v8YDbtao7BLUC3wjASn1inAKLFCjaH1 --mode mockup --no-base-dir-warnings typecheck script michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz --details +Well typed +Gas remaining: 1039990.860 units remaining +{ parameter (pair (pair bytes nat) (contract (ticket bytes))) ; + storage unit ; + code { UNPAIR + /* [ pair (pair bytes nat) (contract (ticket bytes)) : unit ] */ ; + UNPAIR + /* [ pair bytes nat : contract (ticket bytes) : unit ] */ ; + UNPAIR + /* [ bytes : nat : contract (ticket bytes) : unit ] */ ; + TICKET + /* [ option (ticket bytes) : contract (ticket bytes) : unit ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : ticket bytes : contract (ticket bytes) : unit ] */ ; + SWAP + /* [ ticket bytes : mutez : contract (ticket bytes) : unit ] */ ; + TRANSFER_TOKENS + /* [ operation : unit ] */ ; + NIL operation + /* [ list operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } diff --git a/tezt/tests/expected/script_hash_regression.ml/Alpha- Test script hash regression.out b/tezt/tests/expected/script_hash_regression.ml/Alpha- Test script hash regression.out index f278bf05bd7843efb5352c62d541d4d24b800150..72c54d8f00e86ce8244ad8bab9e9eabaf6691618 100644 --- a/tezt/tests/expected/script_hash_regression.ml/Alpha- Test script hash regression.out +++ b/tezt/tests/expected/script_hash_regression.ml/Alpha- Test script hash regression.out @@ -195,6 +195,7 @@ expruyXnWo3aJfqo9Z6ycLDjyJygYCeH5JUrchAfFHZcvU1ebtDBXx michelson_test_scripts/mi exprvJ8zXaBkyXMhJ2eKtPwdwbg5NLrggvW8MEpVK3hk3nAe215PQ6 michelson_test_scripts/mini_scenarios/replay.tz exprtuiYUMjM6d8XxPda1yfKeN61ko6riom35PzybC31NKXkVhgBQy michelson_test_scripts/mini_scenarios/reveal_signed_preimage.tz exprvHREG4G45HEucJxKDgc97zKvtHSHH19EJNGJdTvTjPD4xVW64f michelson_test_scripts/mini_scenarios/sc_rollup_forward.tz +exprtjCFzmoU7Z5DAfA2NX69CdWG68wmgLUKgsNY4THyjBU4kofTF8 michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz expruB4maBvk1y4JaeSLpDXWC3zKiXK5QFYv4B3R5KfdGEt4B5VvTT michelson_test_scripts/mini_scenarios/self_address_receiver.tz exprvTG7hjtWXeogStj3pzM1MCVcNg1q6KnivqNVzQjviUrJvsjfQn michelson_test_scripts/mini_scenarios/self_address_sender.tz exprtahxrrP8ovDPykXLtbNsHGKTA8BwAvcwKCZR9LZtomdEfMaRDP michelson_test_scripts/mini_scenarios/send_ticket_list_016.tz diff --git a/tezt/tests/expected/script_hash_regression.ml/Lima- Test script hash regression.out b/tezt/tests/expected/script_hash_regression.ml/Lima- Test script hash regression.out index 979c6f87ad1013030aa442abf7fa30dde7cc7e60..6b191956e2faf5872f31a5ff4a87da8f8b25e787 100644 --- a/tezt/tests/expected/script_hash_regression.ml/Lima- Test script hash regression.out +++ b/tezt/tests/expected/script_hash_regression.ml/Lima- Test script hash regression.out @@ -195,6 +195,7 @@ expruyXnWo3aJfqo9Z6ycLDjyJygYCeH5JUrchAfFHZcvU1ebtDBXx michelson_test_scripts/mi exprvJ8zXaBkyXMhJ2eKtPwdwbg5NLrggvW8MEpVK3hk3nAe215PQ6 michelson_test_scripts/mini_scenarios/replay.tz exprtuiYUMjM6d8XxPda1yfKeN61ko6riom35PzybC31NKXkVhgBQy michelson_test_scripts/mini_scenarios/reveal_signed_preimage.tz exprvHREG4G45HEucJxKDgc97zKvtHSHH19EJNGJdTvTjPD4xVW64f michelson_test_scripts/mini_scenarios/sc_rollup_forward.tz +exprtjCFzmoU7Z5DAfA2NX69CdWG68wmgLUKgsNY4THyjBU4kofTF8 michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz expruB4maBvk1y4JaeSLpDXWC3zKiXK5QFYv4B3R5KfdGEt4B5VvTT michelson_test_scripts/mini_scenarios/self_address_receiver.tz exprvTG7hjtWXeogStj3pzM1MCVcNg1q6KnivqNVzQjviUrJvsjfQn michelson_test_scripts/mini_scenarios/self_address_sender.tz expru6tUaVWpaR7D5invwY7inJnPZGPXTcDqFvirrHPMRxSeHki5Fz michelson_test_scripts/mini_scenarios/send_tickets_in_big_map_015.tz diff --git a/tezt/tests/expected/script_hash_regression.ml/Mumbai- Test script hash regression.out b/tezt/tests/expected/script_hash_regression.ml/Mumbai- Test script hash regression.out index f278bf05bd7843efb5352c62d541d4d24b800150..72c54d8f00e86ce8244ad8bab9e9eabaf6691618 100644 --- a/tezt/tests/expected/script_hash_regression.ml/Mumbai- Test script hash regression.out +++ b/tezt/tests/expected/script_hash_regression.ml/Mumbai- Test script hash regression.out @@ -195,6 +195,7 @@ expruyXnWo3aJfqo9Z6ycLDjyJygYCeH5JUrchAfFHZcvU1ebtDBXx michelson_test_scripts/mi exprvJ8zXaBkyXMhJ2eKtPwdwbg5NLrggvW8MEpVK3hk3nAe215PQ6 michelson_test_scripts/mini_scenarios/replay.tz exprtuiYUMjM6d8XxPda1yfKeN61ko6riom35PzybC31NKXkVhgBQy michelson_test_scripts/mini_scenarios/reveal_signed_preimage.tz exprvHREG4G45HEucJxKDgc97zKvtHSHH19EJNGJdTvTjPD4xVW64f michelson_test_scripts/mini_scenarios/sc_rollup_forward.tz +exprtjCFzmoU7Z5DAfA2NX69CdWG68wmgLUKgsNY4THyjBU4kofTF8 michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz expruB4maBvk1y4JaeSLpDXWC3zKiXK5QFYv4B3R5KfdGEt4B5VvTT michelson_test_scripts/mini_scenarios/self_address_receiver.tz exprvTG7hjtWXeogStj3pzM1MCVcNg1q6KnivqNVzQjviUrJvsjfQn michelson_test_scripts/mini_scenarios/self_address_sender.tz exprtahxrrP8ovDPykXLtbNsHGKTA8BwAvcwKCZR9LZtomdEfMaRDP michelson_test_scripts/mini_scenarios/send_ticket_list_016.tz diff --git a/tezt/tests/main.ml b/tezt/tests/main.ml index 7172774f84c6f71fcdd244042b72350b9dfe46cb..9c5b06a05597dd00ecc58eb4e2f5b6f008fa26ca 100644 --- a/tezt/tests/main.ml +++ b/tezt/tests/main.ml @@ -81,7 +81,8 @@ let register_protocol_migration_tests () = Voting.register ~from_protocol:migrate_to ~to_protocol:Demo - ~loser_protocols:[migrate_from] + ~loser_protocols:[migrate_from] ; + Sc_rollup.register_migration ~migrate_from:Protocol.Mumbai ~migrate_to (* Tests related to one-off protocol migrations used in the past. *) let register_older_protocol_migration_tests () = diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 51a15dda848225507efa67b90c2a7ea414519453..3bc52f6461d428137e349d66c2ed4726b9a515f2 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -144,6 +144,26 @@ let get_sc_rollup_constants client = timeout_period_in_blocks; } +let originate_forward_smart_contract ?(src = Constant.bootstrap1.alias) client + protocol = + (* Originate forwarder contract to send internal messages to rollup *) + let* alias, contract_id = + Client.originate_contract_at + ~amount:Tez.zero + ~src + ~init:"Unit" + ~burn_cap:Tez.(of_int 1) + client + ["mini_scenarios"; "sc_rollup_forward"] + protocol + in + let* () = Client.bake_for_and_wait client in + Log.info + "The forwarder %s (%s) contract was successfully originated" + alias + contract_id ; + return contract_id + (* List of scoru errors messages used in tests below. *) let commit_too_recent = @@ -273,6 +293,38 @@ let test_l1_scenario ?regression ?hooks ~kind ?boot_sector ?commitment_period in scenario sc_rollup tezos_node tezos_client +let test_l1_migration_scenario ?parameters_ty ?(src = Constant.bootstrap1.alias) + ?variant ?(tags = []) ~kind ~migrate_from ~migrate_to ~scenario_prior + ~scenario_after ~description () = + let tags = kind :: "migration" :: tags in + Test.register + ~__FILE__ + ~tags + ~title:(format_title_scenario kind {variant; tags; description}) + @@ fun () -> + let* tezos_node, tezos_client = + setup_l1 ~commitment_period:10 ~challenge_window:10 ~timeout:10 migrate_from + in + let* sc_rollup = originate_sc_rollup ?parameters_ty ~kind ~src tezos_client in + let* prior_res = scenario_prior tezos_client ~sc_rollup in + let current_level = Node.get_level tezos_node in + let migration_level = current_level + 1 in + let* () = Node.terminate tezos_node in + let patch_config = + Node.Config_file.set_sandbox_network_with_user_activated_upgrades + [(migration_level, migrate_to)] + in + let nodes_args = + Node.[Synchronisation_threshold 0; History_mode Archive; No_bootstrap_peers] + in + let* () = Node.run ~patch_config tezos_node nodes_args in + let* () = Node.wait_for_ready tezos_node in + let* () = + repeat migration_level (fun () -> Client.bake_for_and_wait tezos_client) + in + let* () = scenario_after tezos_client ~sc_rollup prior_res in + unit + let test_full_scenario ?supports ?regression ?hooks ~kind ?mode ?boot_sector ?commitment_period ?(parameters_ty = "string") ?challenge_window ?timeout {variant; tags; description} scenario = @@ -1039,21 +1091,7 @@ let test_rollup_node_advances_pvm_state ?regression ~title ?boot_sector let* level, forwarder = if not internal then return (level, None) else - (* Originate forwarder contract to send internal messages to rollup *) - let* _alias, contract_id = - Client.originate_contract_at - ~amount:Tez.zero - ~src:Constant.bootstrap1.alias - ~init:"Unit" - ~burn_cap:Tez.(of_int 1) - client - ["mini_scenarios"; "sc_rollup_forward"] - protocol - in - let* () = Client.bake_for_and_wait client in - Log.info - "The forwarder %s contract was successfully originated" - contract_id ; + let* contract_id = originate_forward_smart_contract client protocol in return (level + 1, Some contract_id) in (* Called with monotonically increasing [i] *) @@ -3707,20 +3745,6 @@ let test_outbox_message_generic ?supports ?regression ?expected_error string ~error_msg:"Invalid contract storage: expecting '%R', got '%L'.") in - let originate_source_contract () = - let* _alias, address = - Client.originate_contract_at - ~amount:Tez.zero - ~src:Constant.bootstrap1.alias - ~init:"Unit" - ~burn_cap:Tez.(of_int 1) - client - ["mini_scenarios"; "sc_rollup_forward"] - protocol - in - let* () = Client.bake_for_and_wait client in - return address - in let perform_rollup_execution_and_cement source_address target_address = let* payload = input_message sc_client target_address in let* () = @@ -3838,7 +3862,9 @@ let test_outbox_message_generic ?supports ?regression ?expected_error Process.check_error ~msg process) in let* target_contract_address = originate_target_contract () in - let* source_contract_address = originate_source_contract () in + let* source_contract_address = + originate_forward_smart_contract client protocol + in let* () = perform_rollup_execution_and_cement source_contract_address @@ -4324,6 +4350,117 @@ let test_recover_bond_of_stakers = in unit +(** Test that it is still possible to send message after a migration +(internal and external). *) +let test_migration_inbox ~kind ~migrate_from ~migrate_to = + let tags = ["internal"; "external"; "message"; "inbox"] + and description = "testing to send inbox operation post migration." + and scenario_prior tezos_client ~sc_rollup = + let* minter_address = + originate_forward_smart_contract tezos_client migrate_from + in + let* () = send_messages 2 tezos_client in + let* () = + Client.transfer + ~amount:Tez.(of_int 100) + ~burn_cap:Tez.(of_int 100) + ~storage_limit:100000 + ~giver:Constant.bootstrap1.alias + ~receiver:minter_address + ~arg: + (Format.sprintf "Pair 0x%s %S " (hex_encode "pred_message") sc_rollup) + tezos_client + in + return minter_address + and scenario_after tezos_client ~sc_rollup minter_address = + let* () = send_messages 2 tezos_client in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5286 + Check messages are correctly added in the inbox. *) + Client.transfer + ~amount:Tez.(of_int 100) + ~burn_cap:Tez.(of_int 100) + ~storage_limit:100000 + ~giver:Constant.bootstrap1.alias + ~receiver:minter_address + ~arg: + (Format.sprintf "Pair 0x%s %S " (hex_encode "next_message") sc_rollup) + tezos_client + in + test_l1_migration_scenario + ~parameters_ty:"bytes" + ~kind + ~migrate_from + ~migrate_to + ~scenario_prior + ~scenario_after + ~tags + ~description + () + +(** Test to continue to send messages after a migration. *) +let test_migration_ticket_inbox ~kind ~migrate_from ~migrate_to = + let tags = ["internal"; "inbox"; "ticket"] + and description = + "testing to send internal message with ticket post migration." + and scenario_prior tezos_client ~sc_rollup = + (* Originate forwarder contract to send internal messages to rollup *) + let* alias, minter_address = + Client.originate_contract_at + ~amount:Tez.zero + ~src:Constant.bootstrap1.alias + ~init:"Unit" + ~burn_cap:Tez.(of_int 1) + tezos_client + ["mini_scenarios"; "sc_rollup_mint_and_forward"] + migrate_from + in + let* () = Client.bake_for_and_wait tezos_client in + Log.info + "The minter-forwarder %s (%s) contract was successfully originated" + alias + minter_address ; + let* () = + Client.transfer + ~amount:Tez.(of_int 100) + ~burn_cap:Tez.(of_int 100) + ~storage_limit:100000 + ~giver:Constant.bootstrap1.alias + ~receiver:minter_address + ~arg: + (Format.sprintf + "Pair (Pair 0x%s 10) %S " + (hex_encode "pred_message") + sc_rollup) + tezos_client + in + return minter_address + and scenario_after tezos_client ~sc_rollup minter_address = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5286 + Check messages are correctly added in the inbox. *) + Client.transfer + ~amount:Tez.(of_int 100) + ~burn_cap:Tez.(of_int 100) + ~storage_limit:100000 + ~giver:Constant.bootstrap1.alias + ~receiver:minter_address + ~arg: + (Format.sprintf + "Pair (Pair 0x%s 10) %S " + (hex_encode "pred_message") + sc_rollup) + tezos_client + in + test_l1_migration_scenario + ~parameters_ty:"ticket bytes" + ~kind + ~migrate_from + ~migrate_to + ~scenario_prior + ~scenario_after + ~tags + ~description + () + let register ~kind ~protocols = test_origination ~kind protocols ; test_rollup_node_running ~kind protocols ; @@ -4494,3 +4631,11 @@ let register ~protocols = (* Shared tezts - will be executed for both PVMs. *) register ~kind:"wasm_2_0_0" ~protocols ; register ~kind:"arith" ~protocols + +let register_migration ~kind ~migrate_from ~migrate_to = + test_migration_inbox ~kind ~migrate_from ~migrate_to ; + test_migration_ticket_inbox ~kind ~migrate_from ~migrate_to + +let register_migration ~migrate_from ~migrate_to = + register_migration ~kind:"arith" ~migrate_from ~migrate_to ; + register_migration ~kind:"wasm_2_0_0" ~migrate_from ~migrate_to diff --git a/tezt/tests/sc_rollup.mli b/tezt/tests/sc_rollup.mli index 114bf8e2355c17f285debf51de1bb2fda53a82fa..eeeb8569ec9de9e40a8f28c060b919d2b1bcc786 100644 --- a/tezt/tests/sc_rollup.mli +++ b/tezt/tests/sc_rollup.mli @@ -31,3 +31,6 @@ *) val register : protocols:Protocol.t list -> unit + +val register_migration : + migrate_from:Protocol.t -> migrate_to:Protocol.t -> unit