From 22b35af74e433c7809fb7f2769b7d8423b354364 Mon Sep 17 00:00:00 2001 From: Sylvain Ribstein Date: Thu, 17 Aug 2023 18:39:56 +0200 Subject: [PATCH 1/3] rollup/node: exit node when bailout and no stake --- src/lib_smart_rollup_node/daemon_event.ml | 10 ++++++++++ src/lib_smart_rollup_node/daemon_event.mli | 4 ++++ .../rollup_node_daemon.ml | 4 ++++ .../rollup_node_errors.ml | 18 +++++++++++++++++- .../lib_sc_rollup_node/daemon_helpers.ml | 12 ++++++++++++ .../lib_sc_rollup_node/daemon_helpers.ml | 12 ++++++++++++ .../lib_sc_rollup_node/daemon_helpers.ml | 12 ++++++++++++ 7 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/lib_smart_rollup_node/daemon_event.ml b/src/lib_smart_rollup_node/daemon_event.ml index c737ca5f5949..fdca440c8d8a 100644 --- a/src/lib_smart_rollup_node/daemon_event.ml +++ b/src/lib_smart_rollup_node/daemon_event.ml @@ -142,6 +142,14 @@ module Simple = struct commitments." ~level:Error () + + let exit_bailout_mode = + declare_0 + ~section + ~name:"sc_rollup_daemon_exit_bailout_mode" + ~msg:"Stakes have been recovered, and the node is exiting safely now." + ~level:Error + () end let head_processing hash level = Simple.(emit head_processing (hash, level)) @@ -184,3 +192,5 @@ let migration ~catching_up (old_protocol, old_protocol_level) let error e = Simple.(emit error) e let degraded_mode () = Simple.(emit degraded_mode) () + +let exit_bailout_mode () = Simple.(emit exit_bailout_mode) () diff --git a/src/lib_smart_rollup_node/daemon_event.mli b/src/lib_smart_rollup_node/daemon_event.mli index cebe62989b77..96ae022ccc45 100644 --- a/src/lib_smart_rollup_node/daemon_event.mli +++ b/src/lib_smart_rollup_node/daemon_event.mli @@ -69,3 +69,7 @@ val error : tztrace -> unit Lwt.t (** Emit an event for when the node enters the degraded mode to only play refutations. *) val degraded_mode : unit -> unit Lwt.t + +(** Emit an event when the node exits after recovering the operator's + stakes. *) +val exit_bailout_mode : unit -> unit Lwt.t diff --git a/src/lib_smart_rollup_node/rollup_node_daemon.ml b/src/lib_smart_rollup_node/rollup_node_daemon.ml index 3d9d7bf5b781..3523e3468df6 100644 --- a/src/lib_smart_rollup_node/rollup_node_daemon.ml +++ b/src/lib_smart_rollup_node/rollup_node_daemon.ml @@ -431,6 +431,10 @@ let run ({node_ctxt; configuration; plugin; _} as state) = fatal_error_exit e | Rollup_node_errors.Could_not_open_preimage_file _ :: _ as e -> handle_preimage_not_found e + | Rollup_node_errors.Exit_bond_recovered_bailout_mode :: [] -> + let*! () = Daemon_event.exit_bailout_mode () in + let*! _ = Lwt_exit.exit_and_wait 0 in + return_unit | e -> error_to_degraded_mode e) module Internal_for_tests = struct diff --git a/src/lib_smart_rollup_node/rollup_node_errors.ml b/src/lib_smart_rollup_node/rollup_node_errors.ml index 37f4f8c0f847..43c4a573bb38 100644 --- a/src/lib_smart_rollup_node/rollup_node_errors.ml +++ b/src/lib_smart_rollup_node/rollup_node_errors.ml @@ -76,6 +76,8 @@ type error += type error += Operator_not_in_whitelist +type error += Exit_bond_recovered_bailout_mode + let () = register_error_kind `Permanent @@ -399,4 +401,18 @@ let () = `Permanent Data_encoding.unit (function Operator_not_in_whitelist -> Some () | _ -> None) - (fun () -> Operator_not_in_whitelist) + (fun () -> Operator_not_in_whitelist) ; + + register_error_kind + ~id:"sc_rollup.node.exiting_bailout_mode" + ~title:"The rollup node is exiting." + ~description: + "The rollup node is exiting after recovering the bond of the operator." + ~pp:(fun ppf () -> + Format.pp_print_string + ppf + "The rollup node is exiting after bailout mode.") + `Permanent + Data_encoding.unit + (function Exit_bond_recovered_bailout_mode -> Some () | _ -> None) + (fun () -> Exit_bond_recovered_bailout_mode) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon_helpers.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon_helpers.ml index 1aa60be37de5..8602b64367f1 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon_helpers.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon_helpers.ml @@ -273,6 +273,18 @@ let process_included_l1_operation (type kind) (node_ctxt : Node_context.rw) (Sc_rollup_proto_types.Dal.Slot_header.to_octez slot_header) in return_unit + (* If the node is in bailout mode and the bond of the operator has + been recovered then initiate an exit from bailout mode and + gracefully shut down the process. Otherwise, no action is + taken. *) + | Sc_rollup_recover_bond {staker; _}, Sc_rollup_recover_bond_result _ + when Node_context.is_bailout node_ctxt -> ( + match Node_context.get_operator node_ctxt Operating with + | Some operating_pkh -> + fail_when + Signature.Public_key_hash.(operating_pkh = staker) + Sc_rollup_node_errors.Exit_bond_recovered_bailout_mode + | _ -> return_unit) | _, _ -> (* Other manager operations *) return_unit diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/daemon_helpers.ml b/src/proto_018_Proxford/lib_sc_rollup_node/daemon_helpers.ml index 4c072573b6a4..8093066ca481 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/daemon_helpers.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/daemon_helpers.ml @@ -270,6 +270,18 @@ let process_included_l1_operation (type kind) (node_ctxt : Node_context.rw) (Sc_rollup_proto_types.Dal.Slot_header.to_octez slot_header) in return_unit + (* If the node is in bailout mode and the bond of the operator has + been recovered then initiate an exit from bailout mode and + gracefully shut down the process. Otherwise, no action is + taken. *) + | Sc_rollup_recover_bond {staker; _}, Sc_rollup_recover_bond_result _ + when Node_context.is_bailout node_ctxt -> ( + match Node_context.get_operator node_ctxt Operating with + | Some operating_pkh -> + fail_when + Signature.Public_key_hash.(operating_pkh = staker) + Sc_rollup_node_errors.Exit_bond_recovered_bailout_mode + | _ -> return_unit) | _, _ -> (* Other manager operations *) return_unit diff --git a/src/proto_alpha/lib_sc_rollup_node/daemon_helpers.ml b/src/proto_alpha/lib_sc_rollup_node/daemon_helpers.ml index 4c072573b6a4..8093066ca481 100644 --- a/src/proto_alpha/lib_sc_rollup_node/daemon_helpers.ml +++ b/src/proto_alpha/lib_sc_rollup_node/daemon_helpers.ml @@ -270,6 +270,18 @@ let process_included_l1_operation (type kind) (node_ctxt : Node_context.rw) (Sc_rollup_proto_types.Dal.Slot_header.to_octez slot_header) in return_unit + (* If the node is in bailout mode and the bond of the operator has + been recovered then initiate an exit from bailout mode and + gracefully shut down the process. Otherwise, no action is + taken. *) + | Sc_rollup_recover_bond {staker; _}, Sc_rollup_recover_bond_result _ + when Node_context.is_bailout node_ctxt -> ( + match Node_context.get_operator node_ctxt Operating with + | Some operating_pkh -> + fail_when + Signature.Public_key_hash.(operating_pkh = staker) + Sc_rollup_node_errors.Exit_bond_recovered_bailout_mode + | _ -> return_unit) | _, _ -> (* Other manager operations *) return_unit -- GitLab From a58917c2bebaf2cc5c4e1f3df306f326c583dda7 Mon Sep 17 00:00:00 2001 From: Sylvain Ribstein Date: Thu, 17 Aug 2023 18:40:18 +0200 Subject: [PATCH 2/3] tezt/soru: bailout exit when bond is recovered --- tezt/tests/sc_rollup.ml | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 566add4e346e..6e5a03c19ae0 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -6023,11 +6023,12 @@ let bailout_mode_not_publish ~kind = sc_rollup_node "sc_rollup_node_recover_bond.v0" (Fun.const (Some ())) - in - let* _ = Sc_rollup_node.wait_sync sc_rollup_node ~timeout:100. in - let* published_commitment_after = - get_last_published_commitment ~__LOC__ ~hooks sc_rollup_client - in + and* () = + Sc_rollup_node.wait_for + sc_rollup_node + "sc_rollup_daemon_exit_bailout_mode.v0" + (Fun.const (Some ())) + and* exit_error = Sc_rollup_node.wait sc_rollup_node in let* lcc_hash, _level = Sc_rollup_helpers.last_cemented_commitment_hash_with_level ~sc_rollup @@ -6040,26 +6041,23 @@ let bailout_mode_not_publish ~kind = ~error_msg: "Published commitment is not the same as the cemented commitment hash." in - Log.info "Check the last published commitment is the same as before." ; - let () = - Check.( - published_commitment_after.commitment_and_hash.hash - = published_commitment_before.commitment_and_hash.hash) - Check.string - ~error_msg:"Last published commitment have been updated." - in Log.info "The node has submitted the recover_bond operation, and the operator is no \ longer staked." ; - let* operator_balance = contract_balances ~pkh:operator tezos_client in + let* frozen_balance = + RPC.Client.call tezos_client + @@ RPC.get_chain_block_context_contract_frozen_bonds ~id:operator () + in let () = Check.( - (operator_balance.frozen = 0) + (Tez.to_mutez frozen_balance = 0) int ~error_msg: "The operator should not have a stake nor holds a frozen balance.") in - unit + match exit_error with + | WEXITED 0 -> unit + | _ -> failwith "rollup node did not stop gracefully" let custom_mode_empty_operation_kinds ~kind = test_l1_scenario -- GitLab From afa327137d82f0b06b8be844d8ee0b86d6619310 Mon Sep 17 00:00:00 2001 From: Sylvain Ribstein Date: Thu, 17 Aug 2023 18:50:28 +0200 Subject: [PATCH 3/3] changelog: add line for bailout mode --- CHANGES.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index ec17def83608..19f9042fe7b0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -79,6 +79,11 @@ Docker Images Smart Rollup node ----------------- +- A new bailout mode that solely cements and defends existing + commitments without publishing new ones. Recovers bonds when + possible, after which the node exits gracefully. (MR :gl:`!9721`, MR + :gl:`!9817`, MR :gl:`!9835`) + Smart Rollup client ------------------- -- GitLab