From 989c0193a1bb61b708b69e6d63978290c3fe5787 Mon Sep 17 00:00:00 2001 From: Vincent Botbol Date: Tue, 26 Jun 2018 12:37:04 +0200 Subject: [PATCH] Baker: retry once opening node's context on failed checkouts --- .../lib_delegate/client_baking_forge.ml | 26 ++++--- .../lib_delegate/client_baking_simulator.ml | 74 ++++++++++++------- 2 files changed, 62 insertions(+), 38 deletions(-) diff --git a/src/proto_alpha/lib_delegate/client_baking_forge.ml b/src/proto_alpha/lib_delegate/client_baking_forge.ml index 3636ade42..673902bfb 100644 --- a/src/proto_alpha/lib_delegate/client_baking_forge.ml +++ b/src/proto_alpha/lib_delegate/client_baking_forge.ml @@ -21,10 +21,10 @@ let votes_index = 1 let anonymous_index = 2 let managers_index = 3 - type state = { genesis: Block_hash.t ; - index : Context.index ; + context_path: string ; + mutable index : Context.index ; (* see [get_delegates] below to find delegates when the list is empty *) delegates: public_key_hash list ; @@ -38,8 +38,9 @@ type state = { (Time.t * (Client_baking_blocks.block_info * int * public_key_hash)) list ; } -let create_state genesis index delegates constants best = +let create_state genesis context_path index delegates constants best = { genesis ; + context_path ; index ; delegates ; constants ; @@ -312,7 +313,6 @@ let forge_block cctxt ?(chain = `Main) block decode_priority cctxt chain block priority >>=? fun (priority, minimal_timestamp) -> unopt_timestamp timestamp minimal_timestamp >>=? fun timestamp -> - (* get basic building blocks *) let protocol_data = forge_faked_protocol_data ~priority ~seed_nonce_hash in classify_operations ?threshold operations_arg >>=? fun operations -> @@ -449,8 +449,6 @@ let safe_get_unrevealed_nonces cctxt block = lwt_warn "Cannot read nonces: %a@." pp_print_error err >>= fun () -> Lwt.return [] - - let insert_block ?max_priority () @@ -497,12 +495,21 @@ let pop_baking_slots state = state.future_slots <- future_slots ; slots - let filter_invalid_operations (cctxt : #full) state block_info (operations : packed_operation list list) = let open Client_baking_simulator in lwt_debug "Starting client-side validation %a" Block_hash.pp block_info.Client_baking_blocks.hash >>= fun () -> - begin_construction cctxt state.index block_info >>=? fun initial_inc -> + begin begin_construction cctxt state.index block_info >>= function + | Ok inc -> return inc + | Error errs -> + lwt_log_error "Error while fetching current context : %a" + pp_print_error errs >>= fun () -> + lwt_log_notice "Retrying to open the context" >>= fun () -> + Client_baking_simulator.load_context ~context_path:state.context_path >>= fun index -> + begin_construction cctxt index block_info >>=? fun inc -> + state.index <- index; + return inc + end >>=? fun initial_inc -> let endorsements = List.nth operations endorsements_index in let votes = List.nth operations votes_index in let anonymous = List.nth operations anonymous_index in @@ -742,7 +749,7 @@ let create let constants = tzlazy (fun () -> Alpha_services.Constants.all cctxt (`Main, `Head 0)) in Client_baking_simulator.load_context ~context_path >>= fun index -> - let state = create_state genesis_hash index delegates constants bi in + let state = create_state genesis_hash context_path index delegates constants bi in return state in @@ -755,4 +762,3 @@ let create ~compute_timeout ~timeout_k:(bake ?threshold ()) ~event_k:(insert_block ?max_priority ()) - diff --git a/src/proto_alpha/lib_delegate/client_baking_simulator.ml b/src/proto_alpha/lib_delegate/client_baking_simulator.ml index f06db4d4d..2b36529bf 100644 --- a/src/proto_alpha/lib_delegate/client_baking_simulator.ml +++ b/src/proto_alpha/lib_delegate/client_baking_simulator.ml @@ -12,6 +12,22 @@ open Alpha_context module Main = Alpha_environment.Lift(Main) +type error += + | Failed_to_checkout_context + +let () = + register_error_kind + `Permanent + ~id:"Client_baking_simulator.failed_to_checkout_context" + ~title: "Fail during checkout context" + ~description: "" + ~pp:(fun ppf () -> Format.fprintf ppf "@[Failed to checkout the context@]") + Data_encoding.unit + (function + | Failed_to_checkout_context -> Some () + | _ -> None) + (fun () -> Failed_to_checkout_context) + type incremental = { predecessor: Client_baking_blocks.block_info ; context : Context.t ; @@ -25,34 +41,36 @@ let load_context ~context_path = let begin_construction (_cctxt : #Proto_alpha.full) index predecessor = let { Client_baking_blocks.context } = predecessor in - Context.checkout_exn index context >>= fun context -> - let timestamp = Time.now () in - let predecessor_hash = predecessor.hash in - let header : Tezos_base.Block_header.shell_header = Tezos_base.Block_header.{ - predecessor = predecessor_hash ; - proto_level = 0 ; - validation_passes = 0 ; - fitness = predecessor.fitness ; - timestamp ; - level = Raw_level.to_int32 predecessor.level ; - context = Context_hash.zero ; - operations_hash = Operation_list_list_hash.zero ; - } in - Main.begin_construction - ~predecessor_context: context - ~predecessor_timestamp: header.timestamp - ~predecessor_fitness: header.fitness - ~predecessor_level: header.level - ~predecessor:predecessor_hash - ~timestamp - () >>=? fun state -> - return { - predecessor ; - context ; - state ; - rev_operations = [] ; - header ; - } + Context.checkout index context >>= function + | None -> fail Failed_to_checkout_context + | Some context -> + let timestamp = Time.now () in + let predecessor_hash = predecessor.hash in + let header : Tezos_base.Block_header.shell_header = Tezos_base.Block_header.{ + predecessor = predecessor_hash ; + proto_level = 0 ; + validation_passes = 0 ; + fitness = predecessor.fitness ; + timestamp ; + level = Raw_level.to_int32 predecessor.level ; + context = Context_hash.zero ; + operations_hash = Operation_list_list_hash.zero ; + } in + Main.begin_construction + ~predecessor_context: context + ~predecessor_timestamp: header.timestamp + ~predecessor_fitness: header.fitness + ~predecessor_level: header.level + ~predecessor:predecessor_hash + ~timestamp + () >>=? fun state -> + return { + predecessor ; + context ; + state ; + rev_operations = [] ; + header ; + } let add_operation st ( op : Operation.packed ) = Main.apply_operation st.state op >>=? fun (state, _) ->