From 4b40ace87fad030827d1f63b327ab62bd720b7f3 Mon Sep 17 00:00:00 2001 From: Felix Puscasu Date: Thu, 12 Sep 2024 12:12:39 +0100 Subject: [PATCH 1/2] Rollup-Node: Pass PVM module through functions --- .../lib_sc_rollup_node/fueled_pvm.ml | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml b/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml index 41705a512be7..d76a5b830eb5 100644 --- a/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml +++ b/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml @@ -76,8 +76,8 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct [message_index] at a given [level] and this is the [start_tick] of this message processing. If some [failing_ticks] are planned by the loser mode, they will be made. *) - let eval_until_input (node_ctxt : _ Node_context.t) reveal_map level - message_index ~fuel start_tick failing_ticks state = + let eval_until_input (module PVM : Pvm_sig.S) (node_ctxt : _ Node_context.t) + reveal_map level message_index ~fuel start_tick failing_ticks state = let open Lwt_result_syntax in let open Delayed_write_monad.Lwt_result_syntax in let* constants = @@ -91,7 +91,6 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct |> Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez |> Protocol.Alpha_context.Sc_rollup.is_reveal_enabled_predicate in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in let metadata = metadata node_ctxt in let dal_attested_slots_validity_lag = match constants.sc_rollup.reveal_activation_level with @@ -335,13 +334,13 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct [state] to the next step that requires an input. This function is controlled by some [fuel] and may introduce intended failures at some given [failing_ticks]. *) - let feed_input (node_ctxt : _ Node_context.t) reveal_map level message_index - ~fuel ~failing_ticks state input = + let feed_input (module PVM : Pvm_sig.S) (node_ctxt : _ Node_context.t) + reveal_map level message_index ~fuel ~failing_ticks state input = let open Lwt_result_syntax in let open Delayed_write_monad.Lwt_result_syntax in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in let>* res = eval_until_input + (module PVM) node_ctxt reveal_map level @@ -381,6 +380,7 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct let state = PVM.Ctxt_wrapper.to_node_pvmstate state in let>* res = eval_until_input + (module PVM) node_ctxt reveal_map level @@ -396,8 +396,8 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct | Completed {state; fuel; _} -> return (Feed_input_completed {state; fuel}))) - let eval_messages ~reveal_map ~fuel node_ctxt ~message_counter_offset state - inbox_level messages = + let eval_messages ~reveal_map ~fuel (module PVM : Pvm_sig.S) node_ctxt + ~message_counter_offset state inbox_level messages = let open Delayed_write_monad.Lwt_result_syntax in let level = Int32.to_int inbox_level in (* Iterate the PVM state with all the messages. *) @@ -427,6 +427,7 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct in let>* res = feed_input + (module PVM) node_ctxt reveal_map level @@ -459,24 +460,27 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct fuel eval_result Node_context.delayed_write tzresult Lwt.t = let open Lwt_result_syntax in let open Delayed_write_monad.Lwt_result_syntax in - let open (val Pvm.of_kind node_ctxt.kind) in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in (* Obtain inbox and its messages for this block. *) let inbox_level = Octez_smart_rollup.Inbox.inbox_level inbox in - let*! initial_tick = get_tick (Ctxt_wrapper.of_node_pvmstate state) in + let*! initial_tick = + PVM.get_tick (PVM.Ctxt_wrapper.of_node_pvmstate state) + in (* Evaluate all the messages for this level. *) let>* state, remaining_fuel, num_messages, remaining_messages = eval_messages ~reveal_map:None ~fuel + (module PVM) node_ctxt ~message_counter_offset:0 state inbox_level messages in - let pvm_state = Ctxt_wrapper.of_node_pvmstate state in - let*! final_tick = get_tick pvm_state in - let*! state_hash = state_hash pvm_state in + let pvm_state = PVM.Ctxt_wrapper.of_node_pvmstate state in + let*! final_tick = PVM.get_tick pvm_state in + let*! state_hash = PVM.state_hash pvm_state in let num_ticks = Sc_rollup.Tick.distance initial_tick final_tick in let eval_state = { @@ -503,6 +507,7 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct } = let open Lwt_result_syntax in let open Delayed_write_monad.Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in let>* state, remaining_fuel, num_messages, remaining_messages = match messages with | [] -> @@ -516,6 +521,7 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct in let>* res = eval_until_input + (module PVM) node_ctxt reveal_map level @@ -535,17 +541,17 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct eval_messages ~reveal_map ~fuel + (module PVM) node_ctxt ~message_counter_offset state inbox_level messages in - let open (val Pvm.of_kind node_ctxt.kind) in - let pvm_state = Ctxt_wrapper.of_node_pvmstate state in - let*! final_tick = get_tick pvm_state in + let pvm_state = PVM.Ctxt_wrapper.of_node_pvmstate state in + let*! final_tick = PVM.get_tick pvm_state in let final_tick = Sc_rollup.Tick.to_z final_tick in - let*! state_hash = state_hash pvm_state in + let*! state_hash = PVM.state_hash pvm_state in let num_ticks = Z.sub final_tick initial_tick in let eval_state = { -- GitLab From b4d2e8c293572312347cdbf5c319f12c6e833244 Mon Sep 17 00:00:00 2001 From: Felix Puscasu Date: Mon, 16 Sep 2024 03:05:17 +0100 Subject: [PATCH 2/2] Rollup-Node: FUELED_PVM to use mutable PVM API --- .../lib_sc_rollup_node/fueled_pvm.ml | 196 +++++++++--------- 1 file changed, 97 insertions(+), 99 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml b/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml index d76a5b830eb5..f45d1d0518a7 100644 --- a/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml +++ b/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml @@ -31,7 +31,7 @@ open Pvm_plugin_sig module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct type fuel = F.t - type pvm_state = Context.pvmstate + type 'a mut_pvm_impl = (module Pvm_sig.MUTABLE_STATE_S with type t = 'a) let get_reveal ~dac_client ~pre_images_endpoint ~data_dir ~pvm_kind reveal_map hash = @@ -50,9 +50,8 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct Reveals.get ~dac_client ~pre_images_endpoint ~data_dir ~pvm_kind hash type eval_completion = - | Aborted of {state : pvm_state; fuel : fuel; current_tick : int64} + | Aborted of {fuel : fuel; current_tick : int64} | Completed of { - state : pvm_state; fuel : fuel; current_tick : int64; failing_ticks : int64 list; @@ -76,8 +75,10 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct [message_index] at a given [level] and this is the [start_tick] of this message processing. If some [failing_ticks] are planned by the loser mode, they will be made. *) - let eval_until_input (module PVM : Pvm_sig.S) (node_ctxt : _ Node_context.t) - reveal_map level message_index ~fuel start_tick failing_ticks state = + let eval_until_input (type mut_state) + ((module PVM_mut_state) : mut_state mut_pvm_impl) + (node_ctxt : _ Node_context.t) reveal_map level message_index ~fuel + start_tick failing_ticks (state : mut_state) = let open Lwt_result_syntax in let open Delayed_write_monad.Lwt_result_syntax in let* constants = @@ -182,8 +183,8 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct (* This call to the PVM implementation of [eval_many] should never return running more ticks than the given [max_steps] ticks. If it were to happen, this is a security issue, and should be reported as such. *) - let*! state, executed_ticks = - PVM.eval_many + let*! executed_ticks = + PVM_mut_state.eval_many ~reveal_builtins ~write_debug:(Printer node_ctxt.kernel_debug_logger) ~max_steps @@ -198,14 +199,14 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct {max_given = max_steps; executed = executed_ticks} | Some remaining_fuel -> Lwt_result.return remaining_fuel in - return (state, executed_ticks, failing_ticks, remaining_fuel)) + return (executed_ticks, failing_ticks, remaining_fuel)) (function | Error_wrapper error -> Lwt.return (Error error) | exn -> Lwt.reraise exn) in let normal_eval_wrapper state fuel one_step_eval = - let>* state, xticks, fticks, remaining_fuel = normal_eval state fuel in - return (state, xticks, fticks, remaining_fuel, one_step_eval) + let>* xticks, fticks, remaining_fuel = normal_eval state fuel in + return (xticks, fticks, remaining_fuel, one_step_eval) in let failure_insertion_eval state tick = let*! () = @@ -215,8 +216,7 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct ~message_tick:tick ~internal:true in - let*! state = PVM.Internal_for_tests.insert_failure state in - return state + PVM_mut_state.Internal_for_tests.insert_failure state in match failing_ticks with | xtick :: failing_ticks' -> @@ -224,37 +224,31 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct let jump = Int64.(max 0L (pred xtick)) in if Compare.Int64.(jump = 0L) then (* Insert the failure in the first tick. *) - return (state, xtick, failing_ticks', fuel, Some one_step_eval) + return (xtick, failing_ticks', fuel, Some one_step_eval) else (* Jump just before the tick where we'll insert a failure. Nevertheless, we don't execute more than [fuel] steps. *) normal_eval_wrapper state fuel (Some one_step_eval) | _ -> normal_eval_wrapper state fuel None in - let abort (state : PVM.tree) fuel current_tick = - let state = PVM.Ctxt_wrapper.to_node_pvmstate state in - return (Aborted {state; fuel; current_tick}) - in - let complete (state : PVM.tree) fuel current_tick failing_ticks = - let state = PVM.Ctxt_wrapper.to_node_pvmstate state in - return (Completed {state; fuel; current_tick; failing_ticks}) - in + let abort fuel current_tick = return (Aborted {fuel; current_tick}) in let rec go (fuel : fuel) current_tick failing_ticks state = - let*! input_request = PVM.is_input_state ~is_reveal_enabled state in + let*! input_request = + PVM_mut_state.is_input_state ~is_reveal_enabled state + in match input_request with - | No_input_required when F.is_empty fuel -> abort state fuel current_tick + | No_input_required when F.is_empty fuel -> abort fuel current_tick | No_input_required -> ( - let>* state, executed_ticks, failing_ticks, fuel, one_step_advancement - = + let>* executed_ticks, failing_ticks, fuel, one_step_advancement = eval_tick_consume_fuel fuel failing_ticks state in let tick_after_eval_consume = Int64.add current_tick executed_ticks in match one_step_advancement with | None -> go fuel tick_after_eval_consume failing_ticks state | Some one_step_eval -> ( - let>* state = one_step_eval state in + let*! () = one_step_eval state in match F.consume F.one_tick_consumption fuel with - | None -> abort state fuel tick_after_eval_consume + | None -> abort fuel tick_after_eval_consume | Some fuel -> go fuel @@ -263,7 +257,7 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct state)) | Needs_reveal (Reveal_raw_data hash) -> ( match F.consume F.one_tick_consumption fuel with - | None -> abort state fuel current_tick + | None -> abort fuel current_tick | Some fuel -> let* data = get_reveal @@ -274,19 +268,21 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct reveal_map hash in - let*! next_state = PVM.set_input (Reveal (Raw_data data)) state in - go fuel (Int64.succ current_tick) failing_ticks next_state) + let*! () = + PVM_mut_state.set_input (Reveal (Raw_data data)) state + in + go fuel (Int64.succ current_tick) failing_ticks state) | Needs_reveal Reveal_metadata -> ( match F.consume F.one_tick_consumption fuel with - | None -> abort state fuel current_tick + | None -> abort fuel current_tick | Some fuel -> - let*! next_state = - PVM.set_input (Reveal (Metadata metadata)) state + let*! () = + PVM_mut_state.set_input (Reveal (Metadata metadata)) state in - go fuel (Int64.succ current_tick) failing_ticks next_state) + go fuel (Int64.succ current_tick) failing_ticks state) | Needs_reveal (Request_dal_page page_id) -> ( match F.consume F.one_tick_consumption fuel with - | None -> abort state fuel current_tick + | None -> abort fuel current_tick | Some fuel -> let* content_opt = Dal_pages_request.page_content @@ -297,24 +293,26 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct node_ctxt page_id in - let*! next_state = - PVM.set_input (Reveal (Dal_page content_opt)) state + let*! () = + PVM_mut_state.set_input (Reveal (Dal_page content_opt)) state in - go fuel (Int64.succ current_tick) failing_ticks next_state) + go fuel (Int64.succ current_tick) failing_ticks state) | Needs_reveal Reveal_dal_parameters -> ( (* TODO: https://gitlab.com/tezos/tezos/-/issues/6562 Consider supporting revealing of historical DAL parameters. *) match F.consume F.one_tick_consumption fuel with - | None -> abort state fuel current_tick + | None -> abort fuel current_tick | Some fuel -> - let*! next_state = - PVM.set_input (Reveal (Dal_parameters dal_parameters)) state + let*! () = + PVM_mut_state.set_input + (Reveal (Dal_parameters dal_parameters)) + state in - go fuel (Int64.succ current_tick) failing_ticks next_state) + go fuel (Int64.succ current_tick) failing_ticks state) | Initial | First_after _ -> - complete state fuel current_tick failing_ticks + return @@ Completed {fuel; current_tick; failing_ticks} in - go fuel start_tick failing_ticks (PVM.Ctxt_wrapper.of_node_pvmstate state) + go fuel start_tick failing_ticks state (** [mutate input] corrupts the payload of [input] for testing purposes. *) let mutate input = @@ -325,8 +323,8 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct {input with Sc_rollup.payload} type feed_input_completion = - | Feed_input_aborted of {state : pvm_state; fuel : fuel; fed_input : bool} - | Feed_input_completed of {state : pvm_state; fuel : fuel} + | Feed_input_aborted of {fuel : fuel; fed_input : bool} + | Feed_input_completed of fuel (** [feed_input node_ctxt reveal_map level message_index ~fuel ~failing_ticks state input] feeds [input] (that has a given @@ -334,13 +332,15 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct [state] to the next step that requires an input. This function is controlled by some [fuel] and may introduce intended failures at some given [failing_ticks]. *) - let feed_input (module PVM : Pvm_sig.S) (node_ctxt : _ Node_context.t) - reveal_map level message_index ~fuel ~failing_ticks state input = + let feed_input (type mut_state) + ((module PVM_mut_state) : mut_state mut_pvm_impl) + (node_ctxt : _ Node_context.t) reveal_map level message_index ~fuel + ~failing_ticks (state : mut_state) input = let open Lwt_result_syntax in let open Delayed_write_monad.Lwt_result_syntax in let>* res = eval_until_input - (module PVM) + (module PVM_mut_state) node_ctxt reveal_map level @@ -351,11 +351,10 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct state in match res with - | Aborted {state; fuel; _} -> - return (Feed_input_aborted {state; fuel; fed_input = false}) - | Completed {state; fuel; current_tick = tick; failing_ticks} -> ( + | Aborted {fuel; _} -> return (Feed_input_aborted {fuel; fed_input = false}) + | Completed {fuel; current_tick = tick; failing_ticks} -> ( match F.consume F.one_tick_consumption fuel with - | None -> return (Feed_input_aborted {state; fuel; fed_input = false}) + | None -> return (Feed_input_aborted {fuel; fed_input = false}) | Some fuel -> ( let>* input, failing_ticks = match failing_ticks with @@ -372,15 +371,10 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct else return (input, failing_ticks) | [] -> return (input, failing_ticks) in - let*! state = - PVM.set_input - (Inbox_message input) - (PVM.Ctxt_wrapper.of_node_pvmstate state) - in - let state = PVM.Ctxt_wrapper.to_node_pvmstate state in + let*! () = PVM_mut_state.set_input (Inbox_message input) state in let>* res = eval_until_input - (module PVM) + (module PVM_mut_state) node_ctxt reveal_map level @@ -391,23 +385,23 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct state in match res with - | Aborted {state; fuel; _} -> - return (Feed_input_aborted {state; fuel; fed_input = true}) - | Completed {state; fuel; _} -> - return (Feed_input_completed {state; fuel}))) + | Aborted {fuel; _} -> + return (Feed_input_aborted {fuel; fed_input = true}) + | Completed {fuel; _} -> return (Feed_input_completed fuel))) - let eval_messages ~reveal_map ~fuel (module PVM : Pvm_sig.S) node_ctxt - ~message_counter_offset state inbox_level messages = + let eval_messages ~reveal_map ~fuel (type mut_state) + ((module PVM_mut_state) : mut_state mut_pvm_impl) node_ctxt + ~message_counter_offset (state : mut_state) inbox_level messages = let open Delayed_write_monad.Lwt_result_syntax in let level = Int32.to_int inbox_level in (* Iterate the PVM state with all the messages. *) let rec feed_messages (state, fuel) message_index = function | [] -> (* Fed all messages *) - return (state, fuel, message_index - message_counter_offset, []) + return (fuel, message_index - message_counter_offset, []) | messages when F.is_empty fuel -> (* Consumed all fuel *) - return (state, fuel, message_index - message_counter_offset, messages) + return (fuel, message_index - message_counter_offset, messages) | message :: messages -> ( let payload = Sc_rollup.Inbox_message.unsafe_of_string message in let message_counter = Z.of_int message_index in @@ -427,7 +421,7 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct in let>* res = feed_input - (module PVM) + (module PVM_mut_state) node_ctxt reveal_map level @@ -438,20 +432,16 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct input in match res with - | Feed_input_completed {state; fuel} -> + | Feed_input_completed fuel -> feed_messages (state, fuel) (message_index + 1) messages - | Feed_input_aborted {state; fuel; fed_input = false} -> + | Feed_input_aborted {fuel; fed_input = false} -> return - ( state, - fuel, + ( fuel, message_index - message_counter_offset, message :: messages ) - | Feed_input_aborted {state; fuel; fed_input = true} -> - return - ( state, - fuel, - message_index + 1 - message_counter_offset, - messages )) + | Feed_input_aborted {fuel; fed_input = true} -> + return (fuel, message_index + 1 - message_counter_offset, messages) + ) in (feed_messages [@tailcall]) (state, fuel) message_counter_offset messages @@ -461,27 +451,31 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct let open Lwt_result_syntax in let open Delayed_write_monad.Lwt_result_syntax in let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let module PVM_mut_state = PVM.Mutable_state in + let mut_state = + PVM.Ctxt_wrapper.from_imm @@ PVM.Ctxt_wrapper.of_node_pvmstate state + in (* Obtain inbox and its messages for this block. *) let inbox_level = Octez_smart_rollup.Inbox.inbox_level inbox in - let*! initial_tick = - PVM.get_tick (PVM.Ctxt_wrapper.of_node_pvmstate state) - in + let*! initial_tick = PVM_mut_state.get_tick mut_state in (* Evaluate all the messages for this level. *) - let>* state, remaining_fuel, num_messages, remaining_messages = + let>* remaining_fuel, num_messages, remaining_messages = eval_messages ~reveal_map:None ~fuel - (module PVM) + (module PVM_mut_state) node_ctxt ~message_counter_offset:0 - state + mut_state inbox_level messages in - let pvm_state = PVM.Ctxt_wrapper.of_node_pvmstate state in - let*! final_tick = PVM.get_tick pvm_state in - let*! state_hash = PVM.state_hash pvm_state in + let*! final_tick = PVM_mut_state.get_tick mut_state in + let*! state_hash = PVM_mut_state.state_hash mut_state in let num_ticks = Sc_rollup.Tick.distance initial_tick final_tick in + let state = + PVM.Ctxt_wrapper.to_node_pvmstate @@ PVM.Ctxt_wrapper.to_imm mut_state + in let eval_state = { state; @@ -508,7 +502,11 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct let open Lwt_result_syntax in let open Delayed_write_monad.Lwt_result_syntax in let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let>* state, remaining_fuel, num_messages, remaining_messages = + let module PVM_mut_state = PVM.Mutable_state in + let state = + PVM.Ctxt_wrapper.from_imm @@ PVM.Ctxt_wrapper.of_node_pvmstate state + in + let>* remaining_fuel, num_messages, remaining_messages = match messages with | [] -> let level = Int32.to_int inbox_level in @@ -521,7 +519,7 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct in let>* res = eval_until_input - (module PVM) + (module PVM_mut_state) node_ctxt reveal_map level @@ -531,28 +529,28 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct failing_ticks state in - let state, remaining_fuel = - match res with - | Aborted {state; fuel; _} | Completed {state; fuel; _} -> - (state, fuel) + let remaining_fuel = + match res with Aborted {fuel; _} | Completed {fuel; _} -> fuel in - return (state, remaining_fuel, 0, []) + return (remaining_fuel, 0, []) | _ -> eval_messages ~reveal_map ~fuel - (module PVM) + (module PVM_mut_state) node_ctxt ~message_counter_offset state inbox_level messages in - let pvm_state = PVM.Ctxt_wrapper.of_node_pvmstate state in - let*! final_tick = PVM.get_tick pvm_state in + let*! final_tick = PVM_mut_state.get_tick state in let final_tick = Sc_rollup.Tick.to_z final_tick in - let*! state_hash = PVM.state_hash pvm_state in + let*! state_hash = PVM_mut_state.state_hash state in let num_ticks = Z.sub final_tick initial_tick in + let state = + PVM.Ctxt_wrapper.to_node_pvmstate @@ PVM.Ctxt_wrapper.to_imm state + in let eval_state = { state; -- GitLab