diff --git a/manifest/main.ml b/manifest/main.ml index 3b0357a1cbe65baf6d020332fd62860a8dd6943a..f872f12416607691039d5f548cf5409a23644093 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -4335,6 +4335,7 @@ let octez_smart_rollup_node_lib = octez_node_config; prometheus_app; octez_dal_node_lib |> open_; + octez_dac_lib |> open_; octez_dac_client_lib |> open_; octez_injector |> open_; octez_version_value |> open_; @@ -6325,7 +6326,7 @@ let hash = Protocol.hash (* [dac] is needed for the DAC observer client which is not available in Nairobi and earlier. *) dac |> if_some |> if_ N.(number >= 018) |> open_; - octez_dac_lib |> if_ N.(number >= 018) |> open_; + octez_dac_lib |> open_; octez_dac_client_lib |> if_ N.(number >= 018) |> open_; octez_shell_services |> open_; octez_smart_rollup_lib |> open_; diff --git a/opam/octez-smart-rollup-node-PtMumbai.opam b/opam/octez-smart-rollup-node-PtMumbai.opam index 9087c4c147ad42af584b089edc9dd7e505ca1f6e..8ecb52d72069d41d20ff1ffac5978c6a3c0fb8e1 100644 --- a/opam/octez-smart-rollup-node-PtMumbai.opam +++ b/opam/octez-smart-rollup-node-PtMumbai.opam @@ -24,6 +24,7 @@ depends: [ "tezos-workers" "tezos-dal-node-services" "tezos-dal-node-lib" + "tezos-dac-lib" "tezos-shell-services" "octez-smart-rollup" "tezos-smart-rollup-016-PtMumbai" diff --git a/opam/octez-smart-rollup-node-PtNairob.opam b/opam/octez-smart-rollup-node-PtNairob.opam index 1d964adac6d4bdd5a4f19c02124bae6bb855b38c..c1e06755a3e3d60a1d2991dea34c89379717e34e 100644 --- a/opam/octez-smart-rollup-node-PtNairob.opam +++ b/opam/octez-smart-rollup-node-PtNairob.opam @@ -24,6 +24,7 @@ depends: [ "tezos-workers" "tezos-dal-node-services" "tezos-dal-node-lib" + "tezos-dac-lib" "tezos-shell-services" "octez-smart-rollup" "tezos-smart-rollup-017-PtNairob" diff --git a/opam/octez-smart-rollup-node-lib.opam b/opam/octez-smart-rollup-node-lib.opam index fd683afcd1259054efb208a79685e79970947e19..581cc5efb223b279d205b860874ae5e219589289 100644 --- a/opam/octez-smart-rollup-node-lib.opam +++ b/opam/octez-smart-rollup-node-lib.opam @@ -19,6 +19,7 @@ depends: [ "octez-node-config" "prometheus-app" { >= "1.2" } "tezos-dal-node-lib" + "tezos-dac-lib" "tezos-dac-client-lib" "octez-injector" "tezos-version" diff --git a/src/lib_smart_rollup_node/dune b/src/lib_smart_rollup_node/dune index 4940f27ce14ac56ff8837f3ab2cdc9967f57a6c4..f545540ba13f891f475f4fa802858c974f490cdb 100644 --- a/src/lib_smart_rollup_node/dune +++ b/src/lib_smart_rollup_node/dune @@ -16,6 +16,7 @@ octez-node-config prometheus-app tezos-dal-node-lib + tezos-dac-lib tezos-dac-client-lib octez-injector tezos-version.value @@ -30,6 +31,7 @@ -open Tezos_client_base -open Tezos_client_base_unix -open Tezos_dal_node_lib + -open Tezos_dac_lib -open Tezos_dac_client_lib -open Octez_injector -open Tezos_version_value diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/fuel.ml b/src/lib_smart_rollup_node/fuel.ml similarity index 100% rename from src/proto_016_PtMumbai/lib_sc_rollup_node/fuel.ml rename to src/lib_smart_rollup_node/fuel.ml diff --git a/src/lib_smart_rollup_node/node_context.ml b/src/lib_smart_rollup_node/node_context.ml index 477c124b2690ca1b1acd7583777096f80a5d69a6..83c8bc771647f974db7c8ffd1e59dbaa5b7115a5 100644 --- a/src/lib_smart_rollup_node/node_context.ml +++ b/src/lib_smart_rollup_node/node_context.ml @@ -756,6 +756,13 @@ let protocol_of_level node_ctxt level = in Lwt.return (find protocols) +let last_seen_protocol node_ctxt = + let open Lwt_result_syntax in + let+ protocols = Store.Protocols.read node_ctxt.store.protocols in + match protocols with + | None | Some [] -> None + | Some (p :: _) -> Some p.protocol + let save_protocol_info node_ctxt (block : Layer1.header) ~(predecessor : Layer1.header) = let open Lwt_result_syntax in diff --git a/src/lib_smart_rollup_node/node_context.mli b/src/lib_smart_rollup_node/node_context.mli index 7554562347b94757b396a3e81cf46b32b279e769..69c9b0bbb661df146984bde24136396641045310 100644 --- a/src/lib_smart_rollup_node/node_context.mli +++ b/src/lib_smart_rollup_node/node_context.mli @@ -383,6 +383,9 @@ type proto_info = { (** [protocol_of_level t level] returns the protocol of block level [level]. *) val protocol_of_level : _ t -> int32 -> proto_info tzresult Lwt.t +(** Returns the last protocol seen by the rollup node. *) +val last_seen_protocol : _ t -> Protocol_hash.t option tzresult Lwt.t + (** [save_protocol_info t block ~predecessor] saves to disk the protocol information associated to the [block], if there is a protocol change between [block] and [predecessor]. *) diff --git a/src/lib_smart_rollup_node/protocol_plugin_sig.ml b/src/lib_smart_rollup_node/protocol_plugin_sig.ml index 892090be590841c82118385e1e8de19034b0eb14..2c9f52ef69312a16440423ef171673b48e5b55a4 100644 --- a/src/lib_smart_rollup_node/protocol_plugin_sig.ml +++ b/src/lib_smart_rollup_node/protocol_plugin_sig.ml @@ -297,4 +297,6 @@ module type S = sig module Layer1_helpers : LAYER1_HELPERS module L1_processing : L1_PROCESSING + + module Pvm : Pvm_plugin_sig.S end diff --git a/src/lib_smart_rollup_node/protocol_plugins.ml b/src/lib_smart_rollup_node/protocol_plugins.ml index 01571759461c06f527ab4b642bf938e502853333..5c4919b15a441e6e66f4d7433328d44d11924b13 100644 --- a/src/lib_smart_rollup_node/protocol_plugins.ml +++ b/src/lib_smart_rollup_node/protocol_plugins.ml @@ -57,9 +57,29 @@ let register (plugin : proto_plugin) = Plugin.protocol ; Protocol_hash.Table.add proto_plugins Plugin.protocol plugin +let registered_protocols () = + Protocol_hash.Table.to_seq_keys proto_plugins |> List.of_seq + let proto_plugin_for_protocol protocol = Protocol_hash.Table.find proto_plugins protocol |> Option.to_result ~none:[Unsupported_protocol protocol] -let registered_protocols () = - Protocol_hash.Table.to_seq_keys proto_plugins |> List.of_seq +let proto_plugin_for_level node_ctxt level = + let open Lwt_result_syntax in + let* {protocol; _} = Node_context.protocol_of_level node_ctxt level in + let*? plugin = proto_plugin_for_protocol protocol in + return plugin + +let proto_plugin_for_block node_ctxt block_hash = + let open Lwt_result_syntax in + let* level = Node_context.level_of_hash node_ctxt block_hash in + proto_plugin_for_level node_ctxt level + +let last_proto_plugin node_ctxt = + let open Lwt_result_syntax in + let* protocol = Node_context.last_seen_protocol node_ctxt in + match protocol with + | None -> failwith "No known last protocol, cannot get plugin" + | Some protocol -> + let*? plugin = proto_plugin_for_protocol protocol in + return plugin diff --git a/src/lib_smart_rollup_node/protocol_plugins.mli b/src/lib_smart_rollup_node/protocol_plugins.mli index 8da839659113af836e8ddcd51f3edfd6382d131c..f846f0415958271f7f81835e2ea6abe6ee812d00 100644 --- a/src/lib_smart_rollup_node/protocol_plugins.mli +++ b/src/lib_smart_rollup_node/protocol_plugins.mli @@ -29,9 +29,25 @@ type proto_plugin = (module Protocol_plugin_sig.S) rollup node. *) val register : proto_plugin -> unit +(** Returns the list of registered protocols. *) +val registered_protocols : unit -> Protocol_hash.t list + +(** {2 Using the correct protocol plugin} *) + (** Return the protocol plugin for a given protocol (or an error if not supported). *) val proto_plugin_for_protocol : Protocol_hash.t -> proto_plugin tzresult -(** Returns the list of registered protocols. *) -val registered_protocols : unit -> Protocol_hash.t list +(** Return the protocol plugin for a given level (or an error if not + supported). *) +val proto_plugin_for_level : + _ Node_context.t -> int32 -> proto_plugin tzresult Lwt.t + +(** Return the protocol plugin for a given block (or an error if not + supported). *) +val proto_plugin_for_block : + _ Node_context.t -> Block_hash.t -> proto_plugin tzresult Lwt.t + +(** Returns the plugin corresponding to the last protocol seen by the rollup + node. *) +val last_proto_plugin : _ Node_context.t -> proto_plugin tzresult Lwt.t diff --git a/src/lib_smart_rollup_node/pvm_plugin_sig.ml b/src/lib_smart_rollup_node/pvm_plugin_sig.ml new file mode 100644 index 0000000000000000000000000000000000000000..fb86b8e1f33edd4b80d7d3ff801dd903dd88db63 --- /dev/null +++ b/src/lib_smart_rollup_node/pvm_plugin_sig.ml @@ -0,0 +1,110 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +(** Evaluation state for the PVM. *) +type 'fuel eval_state = { + state : Context.tree; (** The actual PVM state. *) + state_hash : State_hash.t; (** Hash of [state]. *) + tick : Z.t; (** Tick of [state]. *) + inbox_level : int32; (** Inbox level in which messages are evaluated. *) + message_counter_offset : int; + (** Offset for message index, which corresponds to the number of + messages of the inbox already evaluated. *) + remaining_fuel : 'fuel; + (** Fuel remaining for the evaluation of the inbox. *) + remaining_messages : string list; + (** Messages of the inbox that remain to be evaluated. *) +} + +type 'fuel eval_result = { + state : 'fuel eval_state; + num_ticks : Z.t; + num_messages : int; +} + +module type FUELED_PVM = sig + type fuel + + (** Evaluation result for the PVM which contains the evaluation state and + additional information. *) + + (** [eval_block_inbox ~fuel node_ctxt (inbox, messages) state] evaluates the + [messages] for the [inbox] in the given [state] of the PVM and returns the + evaluation result containing the new state, the number of messages, the + inbox level and the remaining fuel. *) + val eval_block_inbox : + fuel:fuel -> + _ Node_context.t -> + Inbox.t * string list -> + Context.tree -> + fuel eval_result Node_context.delayed_write tzresult Lwt.t + + (** [eval_messages ?reveal_map ~fuel node_ctxt ~message_counter_offset state + inbox_level messages] evaluates the [messages] for inbox level + [inbox_level] in the given [state] of the PVM and returns the evaluation + results containing the new state, the remaining fuel, and the number of + ticks for the evaluation of these messages. If [messages] is empty, the + PVM progresses until the next input request (within the allocated + [fuel]). [message_counter_offset] is used when we evaluate partial + inboxes, such as during simulation. When [reveal_map] is provided, it is + used as an additional source of data for revelation ticks. *) + val eval_messages : + ?reveal_map:string Utils.Reveal_hash_map.t -> + _ Node_context.t -> + fuel eval_state -> + fuel eval_result Node_context.delayed_write tzresult Lwt.t +end + +module type S = sig + val get_tick : Kind.t -> Context.tree -> Z.t Lwt.t + + val state_hash : Kind.t -> Context.tree -> State_hash.t Lwt.t + + val initial_state : Kind.t -> Context.tree Lwt.t + + val parse_boot_sector : Kind.t -> string -> string option + + val install_boot_sector : + Kind.t -> Context.tree -> string -> Context.tree Lwt.t + + val get_status : _ Node_context.t -> Context.tree -> string Lwt.t + + val get_current_level : Kind.t -> Context.tree -> int32 option Lwt.t + + val start_of_level_serialized : string + + val end_of_level_serialized : string + + val protocol_migration_serialized : string option + + val info_per_level_serialized : + predecessor:Block_hash.t -> predecessor_timestamp:Time.Protocol.t -> string + + module Fueled : sig + module Free : FUELED_PVM with type fuel := Fuel.Free.t + + module Accounted : FUELED_PVM with type fuel := Fuel.Accounted.t + end +end diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/fuel.ml b/src/lib_smart_rollup_node/utils.ml similarity index 54% rename from src/proto_017_PtNairob/lib_sc_rollup_node/fuel.ml rename to src/lib_smart_rollup_node/utils.ml index 0ba889d6e61c8c7769f8bc68b0dc26a29551e36f..08393c25a9300f9c7e66b47638431c57fa202dc9 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/fuel.ml +++ b/src/lib_smart_rollup_node/utils.ml @@ -1,7 +1,7 @@ (*****************************************************************************) (* *) (* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -23,68 +23,8 @@ (* *) (*****************************************************************************) -module type S = sig - type t +module Reveal_hash_map = Map.Make (struct + type t = Dac_plugin.hash - (** [consume consumption fuel] consumes the [consumption] amount from the - original [fuel]. It returns [None] when the [consumption] is greater - than the original [fuel] or [Some remaining_fuel]. *) - val consume : t -> t -> t option - - (** The amount of fuel required to run one PVM tick. - {[ - one_tick_consumption = of_ticks 1L - ]} - *) - val one_tick_consumption : t - - (** [of_ticks ticks] gives the amount of fuel required to execute the amount - of [ticks]. *) - val of_ticks : int64 -> t - - val is_empty : t -> bool - - (** The maximum number of ticks that can be executed with the given amount of - fuel. - {[ - max_ticks ∘ of_ticks = Fun.id - of_ticks ∘ max_ticks = Fun.id - ]} - *) - val max_ticks : t -> int64 -end - -(** Free fuel where consumption has no effect. *) -module Free : S = struct - type t = Free - - let one_tick_consumption = Free - - let of_ticks _ = Free - - let consume _ tank = Some tank - - let is_empty _ = false - - let max_ticks _ = Int64.max_int -end - -(** Accounted fuel where each tick consumes one unit of fuel. *) -module Accounted : S = struct - type t = int64 - - let of_ticks i = - assert (Int64.compare i 0L >= 0) ; - i - - let one_tick_consumption = 1L - - let consume consumption fuel = - if Int64.compare fuel consumption >= 0 then - Some (Int64.sub fuel consumption) - else None - - let is_empty fuel = Int64.compare fuel 0L <= 0 - - let max_ticks fuel_left = Int64.max 0L fuel_left -end + let compare = Dac_plugin.raw_compare +end) diff --git a/src/proto_alpha/lib_sc_rollup_node/fuel.ml b/src/lib_smart_rollup_node/utils.mli similarity index 54% rename from src/proto_alpha/lib_sc_rollup_node/fuel.ml rename to src/lib_smart_rollup_node/utils.mli index 0ba889d6e61c8c7769f8bc68b0dc26a29551e36f..795a71cf73392ad35ab8b5c3510054da94d92bcc 100644 --- a/src/proto_alpha/lib_sc_rollup_node/fuel.ml +++ b/src/lib_smart_rollup_node/utils.mli @@ -1,7 +1,7 @@ (*****************************************************************************) (* *) (* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -23,68 +23,5 @@ (* *) (*****************************************************************************) -module type S = sig - type t - - (** [consume consumption fuel] consumes the [consumption] amount from the - original [fuel]. It returns [None] when the [consumption] is greater - than the original [fuel] or [Some remaining_fuel]. *) - val consume : t -> t -> t option - - (** The amount of fuel required to run one PVM tick. - {[ - one_tick_consumption = of_ticks 1L - ]} - *) - val one_tick_consumption : t - - (** [of_ticks ticks] gives the amount of fuel required to execute the amount - of [ticks]. *) - val of_ticks : int64 -> t - - val is_empty : t -> bool - - (** The maximum number of ticks that can be executed with the given amount of - fuel. - {[ - max_ticks ∘ of_ticks = Fun.id - of_ticks ∘ max_ticks = Fun.id - ]} - *) - val max_ticks : t -> int64 -end - -(** Free fuel where consumption has no effect. *) -module Free : S = struct - type t = Free - - let one_tick_consumption = Free - - let of_ticks _ = Free - - let consume _ tank = Some tank - - let is_empty _ = false - - let max_ticks _ = Int64.max_int -end - -(** Accounted fuel where each tick consumes one unit of fuel. *) -module Accounted : S = struct - type t = int64 - - let of_ticks i = - assert (Int64.compare i 0L >= 0) ; - i - - let one_tick_consumption = 1L - - let consume consumption fuel = - if Int64.compare fuel consumption >= 0 then - Some (Int64.sub fuel consumption) - else None - - let is_empty fuel = Int64.compare fuel 0L <= 0 - - let max_ticks fuel_left = Int64.max 0L fuel_left -end +(** A map addressed by (protocol agnostic) DAC reveal hashes. *) +module Reveal_hash_map : Map.S with type key = Dac_plugin.hash diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml index 3f57f74af55a3b7d1b2611ca0fca8927db668f44..543c032d20c0b3a13682bb40225dba4f56cf94aa 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml @@ -119,14 +119,15 @@ let simulate_messages (node_ctxt : Node_context.ro) block ~reveal_pages let reveal_map = match reveal_pages with | Some pages -> + let (module DAC_plugin) = + WithExceptions.Option.get ~loc:__LOC__ @@ Dac_plugin.get Protocol.hash + in let map = List.fold_left (fun map page -> - let hash = - Sc_rollup_reveal_hash.(hash_string ~scheme:Blake2B [page]) - in - Sc_rollup_reveal_hash.Map.add hash page map) - Sc_rollup_reveal_hash.Map.empty + let hash = DAC_plugin.hash_string ~scheme:Blake2B [page] in + Utils.Reveal_hash_map.add hash page map) + Utils.Reveal_hash_map.empty pages in Some map diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/dune b/src/proto_016_PtMumbai/lib_sc_rollup_node/dune index ff86dd4c55b05bfe74985b4158a3ebd0247e504f..d212f728e6467454fa0dcf0c42716ac186baff7e 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/dune +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/dune @@ -22,6 +22,7 @@ tezos-workers tezos-dal-node-services tezos-dal-node-lib + tezos-dac-lib tezos-shell-services octez-smart-rollup tezos-smart-rollup-016-PtMumbai @@ -56,6 +57,7 @@ -open Tezos_protocol_016_PtMumbai_parameters -open Tezos_workers -open Tezos_dal_node_lib + -open Tezos_dac_lib -open Tezos_shell_services -open Octez_smart_rollup -open Tezos_smart_rollup_016_PtMumbai diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/fueled_pvm.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/fueled_pvm.ml index bb35157ecaeb38f4162a7469f75985381fefba1d..4aa526d76528610d1db4abac24f0c7b5b7b955d7 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/fueled_pvm.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/fueled_pvm.ml @@ -26,82 +26,21 @@ open Protocol open Alpha_context module Inbox = Sc_rollup.Inbox -open Protocol -open Alpha_context - -module type S = sig - type fuel - - type pvm_state = Context.tree - - (** Evaluation state for the PVM. *) - type eval_state = { - state : pvm_state; (** The actual PVM state. *) - state_hash : Sc_rollup.State_hash.t; (** Hash of [state]. *) - tick : Sc_rollup.Tick.t; (** Tick of [state]. *) - inbox_level : int32; (** Inbox level in which messages are evaluated. *) - message_counter_offset : int; - (** Offset for message index, which corresponds to the number of - messages of the inbox already evaluated. *) - remaining_fuel : fuel; - (** Fuel remaining for the evaluation of the inbox. *) - remaining_messages : string list; - (** Messages of the inbox that remain to be evaluated. *) - } - - (** Evaluation result for the PVM which contains the evaluation state and - additional information. *) - type eval_result = {state : eval_state; num_ticks : Z.t; num_messages : int} +open Pvm_plugin_sig - (** [eval_block_inbox ~fuel node_ctxt (inbox, messages) state] evaluates the - [messages] for the [inbox] in the given [state] of the PVM and returns the - evaluation result containing the new state, the number of messages, the - inbox level and the remaining fuel. *) - val eval_block_inbox : - fuel:fuel -> - _ Node_context.t -> - Octez_smart_rollup.Inbox.t * string list -> - pvm_state -> - eval_result Node_context.delayed_write tzresult Lwt.t - - (** [eval_messages ?reveal_map ~fuel node_ctxt ~message_counter_offset state - inbox_level messages] evaluates the [messages] for inbox level - [inbox_level] in the given [state] of the PVM and returns the evaluation - results containing the new state, the remaining fuel, and the number of - ticks for the evaluation of these messages. If [messages] is empty, the - PVM progresses until the next input request (within the allocated - [fuel]). [message_counter_offset] is used when we evaluate partial - inboxes, such as during simulation. When [reveal_map] is provided, it is - used as an additional source of data for revelation ticks. *) - val eval_messages : - ?reveal_map:string Sc_rollup_reveal_hash.Map.t -> - _ Node_context.t -> - eval_state -> - eval_result Node_context.delayed_write tzresult Lwt.t -end - -module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct +module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct type fuel = F.t type pvm_state = Context.tree - type eval_state = { - state : pvm_state; - state_hash : Sc_rollup.State_hash.t; - tick : Sc_rollup.Tick.t; - inbox_level : int32; - message_counter_offset : int; - remaining_fuel : fuel; - remaining_messages : string list; - } - - type eval_result = {state : eval_state; num_ticks : Z.t; num_messages : int} - let get_reveal ~data_dir ~pvm_kind reveal_map hash = let found_in_map = match reveal_map with | None -> None - | Some map -> Sc_rollup_reveal_hash.Map.find_opt hash map + | Some map -> + Utils.Reveal_hash_map.find_opt + (Reveals.proto_hash_to_dac_hash hash) + map in match found_in_map with | Some data -> return data @@ -427,7 +366,7 @@ module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct let eval_block_inbox ~fuel (node_ctxt : _ Node_context.t) (inbox, messages) (state : pvm_state) : - eval_result Node_context.delayed_write tzresult Lwt.t = + 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 module PVM = (val Pvm.of_kind node_ctxt.kind) in @@ -451,8 +390,8 @@ module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct let eval_state = { state; - state_hash; - tick = final_tick; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; + tick = Sc_rollup.Tick.to_z final_tick; inbox_level; message_counter_offset = num_messages; remaining_fuel; @@ -513,12 +452,13 @@ module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct messages in let*! final_tick = PVM.get_tick state in + let final_tick = Sc_rollup.Tick.to_z final_tick in let*! state_hash = PVM.state_hash state in - let num_ticks = Sc_rollup.Tick.distance initial_tick final_tick in + let num_ticks = Z.sub final_tick initial_tick in let eval_state = { state; - state_hash; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; tick = final_tick; inbox_level; message_counter_offset = message_counter_offset + num_messages; diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.ml index b246c1777d1f7acf2f48aa76ea11202e099357ce..1a72e4792bf8c7fb5207a3753fe0715e4a669648 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.ml @@ -26,48 +26,23 @@ open Protocol open Alpha_context -(** [get_boot_sector block_hash node_ctxt] fetches the operations in the - [block_hash] and looks for the bootsector used to originate the rollup we're - following. It must be called with [block_hash.level] = - [node_ctxt.genesis_info.level]. *) let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in - let exception Found_boot_sector of string in - let* block = Layer1_helpers.fetch_tezos_block node_ctxt.l1_ctxt block_hash in - let missing_boot_sector () = - failwith "Boot sector not found in Tezos block %a" Block_hash.pp block_hash - in - Lwt.catch - (fun () -> - let apply (type kind) accu ~source:_ (operation : kind manager_operation) - (result : kind Apply_results.successful_manager_operation_result) = - match (operation, result) with - | ( Sc_rollup_originate {kind; boot_sector; _}, - Sc_rollup_originate_result {address; _} ) - when Octez_smart_rollup.Address.( - node_ctxt.rollup_address - = Sc_rollup_proto_types.Address.to_octez address) - && node_ctxt.kind = Sc_rollup_proto_types.Kind.to_octez kind -> - raise (Found_boot_sector boot_sector) - | _ -> accu - in - let apply_internal (type kind) accu ~source:_ - (_operation : kind Apply_internal_results.internal_operation) - (_result : - kind Apply_internal_results.successful_internal_operation_result) = - accu - in - let*? () = - Layer1_services.( - process_applied_manager_operations - (Ok ()) - block.operations - {apply; apply_internal}) + match node_ctxt.boot_sector_file with + | None -> Layer1_helpers.get_boot_sector block_hash node_ctxt + | Some boot_sector_file -> + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let*! boot_sector = Lwt_utils_unix.read_file boot_sector_file in + let*? boot_sector = + Option.value_e + ~error: + [ + Sc_rollup_node_errors.Unparsable_boot_sector + {path = boot_sector_file}; + ] + (PVM.parse_boot_sector boot_sector) in - missing_boot_sector ()) - (function - | Found_boot_sector boot_sector -> return boot_sector - | _ -> missing_boot_sector ()) + return boot_sector let genesis_state block_hash node_ctxt ctxt = let open Lwt_result_syntax in @@ -110,8 +85,6 @@ let transition_pvm node_ctxt ctxt predecessor Layer1.{hash = _; _} } = Delayed_write_monad.apply node_ctxt eval_result in - let state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash in - let tick = Sc_rollup.Tick.to_z tick in let module PVM = (val Pvm.of_kind node_ctxt.kind) in let*! ctxt = PVM.State.set ctxt state in let*! initial_tick = PVM.get_tick predecessor_state in @@ -178,12 +151,12 @@ let start_state_of_block node_ctxt (block : Sc_rollup_block.t) = @ [unsafe_to_string end_of_level_serialized] in return - Fueled_pvm.Accounted. + Pvm_plugin_sig. { state; - state_hash; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; inbox_level; - tick; + tick = Sc_rollup.Tick.to_z tick; message_counter_offset = 0; remaining_fuel = Fuel.Accounted.of_ticks 0L; remaining_messages = messages; @@ -194,8 +167,7 @@ let start_state_of_block node_ctxt (block : Sc_rollup_block.t) = let run_to_tick node_ctxt start_state tick = let open Delayed_write_monad.Lwt_result_syntax in let tick_distance = - Sc_rollup.Tick.distance tick start_state.Fueled_pvm.Accounted.tick - |> Z.to_int64 + Z.sub tick start_state.Pvm_plugin_sig.tick |> Z.to_int64 in let>+ eval_result = Fueled_pvm.Accounted.eval_messages @@ -209,7 +181,7 @@ let state_of_tick_aux node_ctxt ~start_state (event : Sc_rollup_block.t) tick = let* start_state = match start_state with | Some start_state - when start_state.Fueled_pvm.Accounted.inbox_level = event.header.level -> + when start_state.Pvm_plugin_sig.inbox_level = event.header.level -> return start_state | _ -> (* Recompute start state on level change or if we don't have a @@ -229,13 +201,11 @@ module Tick_state_cache = (Aches.Rache.Transfer (Aches.Rache.LRU) (struct - type t = Sc_rollup.Tick.t * Block_hash.t + type t = Z.t * Block_hash.t - let equal (t1, b1) (t2, b2) = - Sc_rollup.Tick.(t1 = t2) && Block_hash.(b1 = b2) + let equal (t1, b1) (t2, b2) = Z.equal t1 t2 && Block_hash.(b1 = b2) - let hash (tick, block) = - ((Sc_rollup.Tick.to_z tick |> Z.hash) * 13) + Block_hash.hash block + let hash (tick, block) = (Z.hash tick * 13) + Block_hash.hash block end)) let tick_state_cache = Tick_state_cache.create 64 (* size of 2 dissections *) @@ -252,16 +222,14 @@ let memo_state_of_tick_aux node_ctxt ~start_state (event : Sc_rollup_block.t) (** [state_of_tick node_ctxt ?start_state tick level] returns [Some end_state] for a given [tick] if this [tick] happened before [level]. Otherwise, returns [None].*) -let state_of_tick node_ctxt ?start_state tick level = +let state_of_tick node_ctxt ?start_state ~tick level = let open Lwt_result_syntax in let level = Raw_level.to_int32 level in - let tick = Sc_rollup.Tick.to_z tick in let* event = Node_context.block_with_tick node_ctxt ~max_level:level tick in match event with | None -> return_none | Some event -> assert (event.header.level <= level) ; - let tick = Sc_rollup.Tick.of_z tick in let* result_state = if Node_context.is_loser node_ctxt then (* TODO: https://gitlab.com/tezos/tezos/-/issues/5253 diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.mli index 124eaa96b53d4ba69484ba4dcc81688166aba0b2..acf81542788bac8866fabe73d00f89ba47fd9585 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.mli @@ -41,16 +41,16 @@ val process_head : Octez_smart_rollup.Inbox.t * string list -> ('a Context.t * int * int64 * Z.t) tzresult Lwt.t -(** [state_of_tick node_ctxt ?start_state tick level] returns [Some (state, +(** [state_of_tick node_ctxt ?start_state ~tick level] returns [Some (state, hash)] for a given [tick] if this [tick] happened before [level]. Otherwise, returns [None]. If provided, the evaluation is resumed from [start_state]. *) val state_of_tick : _ Node_context.t -> - ?start_state:Fueled_pvm.Accounted.eval_state -> - Sc_rollup.Tick.t -> + ?start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state -> + tick:Z.t -> Raw_level.t -> - Fueled_pvm.Accounted.eval_state option tzresult Lwt.t + Fuel.Accounted.t Pvm_plugin_sig.eval_state option tzresult Lwt.t (** [state_of_head node_ctxt ctxt head] returns the state corresponding to the block [head], or the state at rollup genesis if the block is before the diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.ml index cf934fb1b3e7cb8f7e70db74800b64bd9566bfad..6a56c29476b03e121fd14e90d9faaef70c222d39 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.ml @@ -181,3 +181,43 @@ let retrieve_genesis_info cctxt rollup_address = commitment_hash = Sc_rollup_proto_types.Commitment_hash.to_octez commitment_hash; } + +let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = + let open Protocol in + let open Alpha_context in + let open Lwt_result_syntax in + let exception Found_boot_sector of string in + let* block = fetch_tezos_block node_ctxt.l1_ctxt block_hash in + let missing_boot_sector () = + failwith "Boot sector not found in Tezos block %a" Block_hash.pp block_hash + in + Lwt.catch + (fun () -> + let apply (type kind) accu ~source:_ (operation : kind manager_operation) + (result : kind Apply_results.successful_manager_operation_result) = + match (operation, result) with + | ( Sc_rollup_originate {boot_sector; _}, + Sc_rollup_originate_result {address; _} ) + when Octez_smart_rollup.Address.( + node_ctxt.rollup_address + = Sc_rollup_proto_types.Address.to_octez address) -> + raise (Found_boot_sector boot_sector) + | _ -> accu + in + let apply_internal (type kind) accu ~source:_ + (_operation : kind Apply_internal_results.internal_operation) + (_result : + kind Apply_internal_results.successful_internal_operation_result) = + accu + in + let*? () = + Layer1_services.( + process_applied_manager_operations + (Ok ()) + block.operations + {apply; apply_internal}) + in + missing_boot_sector ()) + (function + | Found_boot_sector boot_sector -> return boot_sector + | _ -> missing_boot_sector ()) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.mli index c82972f95ba0d8f23472993bc7451a0655999f68..76a3f7222957d860b9089aee96303939bcfc5de4 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.mli @@ -68,3 +68,8 @@ val retrieve_constants : val retrieve_genesis_info : #Client_context.full -> Address.t -> Node_context.genesis_info tzresult Lwt.t + +(** [get_boot_sector block_hash node_ctxt] retrieves the boot sector from the + rollup origination operation in block [block_hash]. Precondition: + [block_hash] has to be the block where the rollup was originated. *) +val get_boot_sector : Block_hash.t -> _ Node_context.t -> string tzresult Lwt.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/pvm_plugin.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/pvm_plugin.ml new file mode 100644 index 0000000000000000000000000000000000000000..345a8a4e808b7092bbdcf4ce49a95b83491cfbee --- /dev/null +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/pvm_plugin.ml @@ -0,0 +1,84 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) +open Protocol +open Alpha_context + +let get_tick kind state = + let open Lwt_syntax in + let module PVM = (val Pvm.of_kind kind) in + let+ tick = PVM.get_tick state in + Sc_rollup.Tick.to_z tick + +let state_hash kind state = + let open Lwt_syntax in + let module PVM = (val Pvm.of_kind kind) in + let+ hash = PVM.state_hash state in + Sc_rollup_proto_types.State_hash.to_octez hash + +let initial_state kind = + let module PVM = (val Pvm.of_kind kind) in + PVM.initial_state ~empty:(PVM.State.empty ()) + +let parse_boot_sector kind = + let module PVM = (val Pvm.of_kind kind) in + PVM.parse_boot_sector + +let install_boot_sector kind state boot_sector = + let module PVM = (val Pvm.of_kind kind) in + PVM.install_boot_sector state boot_sector + +let get_status node_ctxt state = + let open Lwt_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.Node_context.kind) in + let+ status = PVM.get_status state in + PVM.string_of_status status + +let get_current_level kind state = + let open Lwt_option_syntax in + let module PVM = (val Pvm.of_kind kind) in + let+ current_level = PVM.get_current_level state in + Raw_level.to_int32 current_level + +module Fueled = Fueled_pvm + +let start_of_level_serialized = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string start_of_level_serialized + +let end_of_level_serialized = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string end_of_level_serialized + +let protocol_migration_serialized = None + +let info_per_level_serialized ~predecessor ~predecessor_timestamp = + let info_per_level = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Sc_rollup_inbox_message_repr.( + serialize + (Internal (Info_per_level {predecessor; predecessor_timestamp}))) + in + Sc_rollup_inbox_message_repr.unsafe_to_string info_per_level diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/pvm_plugin.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/pvm_plugin.mli new file mode 100644 index 0000000000000000000000000000000000000000..e0183f81e6368cf6a620b4ec9d3c185465b832bc --- /dev/null +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/pvm_plugin.mli @@ -0,0 +1,27 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +include Pvm_plugin_sig.S diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml index a823250a21b3770417a5aaebc233ca4bcc5bb3c0..38b0f8895d1c0650b80936d8c3ed76bb919db9eb 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml @@ -321,22 +321,26 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = type pvm_intermediate_state = | Hash of Sc_rollup.State_hash.t - | Evaluated of Fueled_pvm.Accounted.eval_state + | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok our_view = let open Lwt_result_syntax in let state_of_tick ?start_state tick = - Interpreter.state_of_tick node_ctxt ?start_state tick last_level + Interpreter.state_of_tick + node_ctxt + ?start_state + ~tick:(Sc_rollup.Tick.to_z tick) + last_level in - let state_hash_of_eval_state Fueled_pvm.Accounted.{state_hash; _} = - state_hash + let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = + Sc_rollup_proto_types.State_hash.of_octez state_hash in let start_hash, start_tick, start_state = match ok with | Hash hash, tick -> (hash, tick, None) | Evaluated ({state_hash; _} as state), tick -> - (state_hash, tick, Some state) + (Sc_rollup_proto_types.State_hash.of_octez state_hash, tick, Some state) in let start_chunk = Sc_rollup.Dissection_chunk.{state_hash = Some start_hash; tick = start_tick} @@ -344,7 +348,8 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok let our_state, our_tick = our_view in let our_state_hash = Option.map - (fun Fueled_pvm.Accounted.{state_hash; _} -> state_hash) + (fun Pvm_plugin_sig.{state_hash; _} -> + Sc_rollup_proto_types.State_hash.of_octez state_hash) our_state in let our_stop_chunk = @@ -396,7 +401,11 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent | Evaluated ok_state, _ -> Some ok_state in let* our = - Interpreter.state_of_tick node_ctxt ?start_state tick game.inbox_level + Interpreter.state_of_tick + node_ctxt + ?start_state + ~tick:(Sc_rollup.Tick.to_z tick) + game.inbox_level in match (their_hash, our) with | None, None -> @@ -405,8 +414,11 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent assert false | Some _, None | None, Some _ -> return (ok, (our, tick)) | Some their_hash, Some ({state_hash = our_hash; _} as our_state) -> - if Sc_rollup.State_hash.equal our_hash their_hash then - traverse (Evaluated our_state, tick) dissection + if + Sc_rollup.State_hash.equal + (Sc_rollup_proto_types.State_hash.of_octez our_hash) + their_hash + then traverse (Evaluated our_state, tick) dissection else return (ok, (our, tick))) in match dissection with @@ -438,7 +450,10 @@ let next_move node_ctxt ~opponent game = let open Lwt_result_syntax in let final_move start_tick = let* start_state = - Interpreter.state_of_tick node_ctxt start_tick game.inbox_level + Interpreter.state_of_tick + node_ctxt + ~tick:(Sc_rollup.Tick.to_z start_tick) + game.inbox_level in match start_state with | None -> diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/reveals.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/reveals.ml index a64538301d1c0bdbd758c72496ba9daa8b41ac33..eccd18d9b8576e3f899299e0dd10312baa9c6d89 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/reveals.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/reveals.ml @@ -75,6 +75,11 @@ let path data_dir pvm_name hash = let hash = hash_to_hex hash in Filename.(concat (concat data_dir pvm_name) hash) +let proto_hash_to_dac_hash ((module Plugin) : Dac_plugin.t) proto_reveal_hash = + proto_reveal_hash + |> Data_encoding.Binary.to_bytes_exn Protocol.Sc_rollup_reveal_hash.encoding + |> Data_encoding.Binary.of_bytes_exn Plugin.encoding + let get ~data_dir ~pvm_kind ~hash = let open Lwt_result_syntax in let filename = @@ -103,3 +108,9 @@ let get ~data_dir ~pvm_kind ~hash = |> return in return contents + +let proto_hash_to_dac_hash proto_reveal_hash = + let dac_plugin = + WithExceptions.Option.get ~loc:__LOC__ @@ Dac_plugin.get Protocol.hash + in + proto_hash_to_dac_hash dac_plugin proto_reveal_hash diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/reveals.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/reveals.mli index f218cab75d38acd05a0acc9cdbd3d4e91edc3d03..53ad954bf3fe40ac17d98442db4f328c9fb2c2e7 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/reveals.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/reveals.mli @@ -71,3 +71,6 @@ val get : pvm_kind:Kind.t -> hash:Protocol.Sc_rollup_reveal_hash.t -> string tzresult Lwt.t + +(** Conversion from protocol reveal hash to protocol agnostic DAC hash. *) +val proto_hash_to_dac_hash : Protocol.Sc_rollup_reveal_hash.t -> Dac_plugin.hash diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/rollup_node_plugin.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/rollup_node_plugin.ml index 6d1642bf8f58d15e8da5aaa7e91613cda1a8d4b5..af7636f504dcbdb831999a50e1acfffc03eb3630 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/rollup_node_plugin.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/rollup_node_plugin.ml @@ -40,6 +40,8 @@ module Plugin : Protocol_plugin_sig.S = struct let process_l1_block_operations = Daemon.process_l1_block_operations end + + module Pvm = Pvm_plugin end let () = Protocol_plugins.register (module Plugin) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.ml index ae34e8b10bc3109c7de2abeefa1261c627c226c4..1b578613831f06448b0c3fd8605ac0bbc3db0d78 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.ml @@ -38,7 +38,7 @@ type t = { ctxt : Context.ro; inbox_level : int32; state : Context.tree; - reveal_map : string Sc_rollup_reveal_hash.Map.t option; + reveal_map : string Utils.Reveal_hash_map.t option; nb_messages_inbox : int; level_position : level_position; info_per_level : info_per_level; @@ -95,11 +95,11 @@ let simulate_messages_no_checks (node_ctxt : Node_context.ro) let*! state_hash = PVM.state_hash state in let*! tick = PVM.get_tick state in let eval_state = - Fueled_pvm. + Pvm_plugin_sig. { state; - state_hash; - tick; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; + tick = Sc_rollup.Tick.to_z tick; inbox_level; message_counter_offset = nb_messages_inbox; remaining_fuel = Fuel.Free.of_ticks 0L; @@ -110,7 +110,7 @@ let simulate_messages_no_checks (node_ctxt : Node_context.ro) let* eval_result = Fueled_pvm.eval_messages ?reveal_map node_ctxt eval_state in - let Fueled_pvm.{state = {state; _}; num_ticks; num_messages; _} = + let Pvm_plugin_sig.{state = {state; _}; num_ticks; num_messages; _} = Delayed_write_monad.ignore eval_result in let*! ctxt = PVM.State.set ctxt state in diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.mli index ac8d8dd036249ecc7567d4dc7b952bd691ec4675..745ead3df5624cee2fdf4fc84c4486a0c554c18f 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.mli @@ -23,7 +23,6 @@ (* *) (*****************************************************************************) -open Protocol open Protocol.Alpha_context module Fueled_pvm = Fueled_pvm.Free @@ -39,7 +38,7 @@ type t = { ctxt : Context.ro; inbox_level : int32; state : Context.tree; - reveal_map : string Sc_rollup_reveal_hash.Map.t option; + reveal_map : string Utils.Reveal_hash_map.t option; nb_messages_inbox : int; level_position : level_position; info_per_level : info_per_level; @@ -49,7 +48,7 @@ type t = { on top} of [block], i.e. for an hypothetical new inbox (level). *) val start_simulation : Node_context.ro -> - reveal_map:string Sc_rollup_reveal_hash.Map.t option -> + reveal_map:string Utils.Reveal_hash_map.t option -> Layer1.head -> t tzresult Lwt.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml index 3f57f74af55a3b7d1b2611ca0fca8927db668f44..543c032d20c0b3a13682bb40225dba4f56cf94aa 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml @@ -119,14 +119,15 @@ let simulate_messages (node_ctxt : Node_context.ro) block ~reveal_pages let reveal_map = match reveal_pages with | Some pages -> + let (module DAC_plugin) = + WithExceptions.Option.get ~loc:__LOC__ @@ Dac_plugin.get Protocol.hash + in let map = List.fold_left (fun map page -> - let hash = - Sc_rollup_reveal_hash.(hash_string ~scheme:Blake2B [page]) - in - Sc_rollup_reveal_hash.Map.add hash page map) - Sc_rollup_reveal_hash.Map.empty + let hash = DAC_plugin.hash_string ~scheme:Blake2B [page] in + Utils.Reveal_hash_map.add hash page map) + Utils.Reveal_hash_map.empty pages in Some map diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/dune b/src/proto_017_PtNairob/lib_sc_rollup_node/dune index 00cf5b4771dc1295a5682e62fd43578d26f0af56..142fff8a2770c514b6b18923d3bfab1132e0beb7 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/dune +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/dune @@ -22,6 +22,7 @@ tezos-workers tezos-dal-node-services tezos-dal-node-lib + tezos-dac-lib tezos-shell-services octez-smart-rollup tezos-smart-rollup-017-PtNairob @@ -56,6 +57,7 @@ -open Tezos_protocol_017_PtNairob_parameters -open Tezos_workers -open Tezos_dal_node_lib + -open Tezos_dac_lib -open Tezos_shell_services -open Octez_smart_rollup -open Tezos_smart_rollup_017_PtNairob diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/fueled_pvm.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/fueled_pvm.ml index bb35157ecaeb38f4162a7469f75985381fefba1d..4aa526d76528610d1db4abac24f0c7b5b7b955d7 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/fueled_pvm.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/fueled_pvm.ml @@ -26,82 +26,21 @@ open Protocol open Alpha_context module Inbox = Sc_rollup.Inbox -open Protocol -open Alpha_context - -module type S = sig - type fuel - - type pvm_state = Context.tree - - (** Evaluation state for the PVM. *) - type eval_state = { - state : pvm_state; (** The actual PVM state. *) - state_hash : Sc_rollup.State_hash.t; (** Hash of [state]. *) - tick : Sc_rollup.Tick.t; (** Tick of [state]. *) - inbox_level : int32; (** Inbox level in which messages are evaluated. *) - message_counter_offset : int; - (** Offset for message index, which corresponds to the number of - messages of the inbox already evaluated. *) - remaining_fuel : fuel; - (** Fuel remaining for the evaluation of the inbox. *) - remaining_messages : string list; - (** Messages of the inbox that remain to be evaluated. *) - } - - (** Evaluation result for the PVM which contains the evaluation state and - additional information. *) - type eval_result = {state : eval_state; num_ticks : Z.t; num_messages : int} +open Pvm_plugin_sig - (** [eval_block_inbox ~fuel node_ctxt (inbox, messages) state] evaluates the - [messages] for the [inbox] in the given [state] of the PVM and returns the - evaluation result containing the new state, the number of messages, the - inbox level and the remaining fuel. *) - val eval_block_inbox : - fuel:fuel -> - _ Node_context.t -> - Octez_smart_rollup.Inbox.t * string list -> - pvm_state -> - eval_result Node_context.delayed_write tzresult Lwt.t - - (** [eval_messages ?reveal_map ~fuel node_ctxt ~message_counter_offset state - inbox_level messages] evaluates the [messages] for inbox level - [inbox_level] in the given [state] of the PVM and returns the evaluation - results containing the new state, the remaining fuel, and the number of - ticks for the evaluation of these messages. If [messages] is empty, the - PVM progresses until the next input request (within the allocated - [fuel]). [message_counter_offset] is used when we evaluate partial - inboxes, such as during simulation. When [reveal_map] is provided, it is - used as an additional source of data for revelation ticks. *) - val eval_messages : - ?reveal_map:string Sc_rollup_reveal_hash.Map.t -> - _ Node_context.t -> - eval_state -> - eval_result Node_context.delayed_write tzresult Lwt.t -end - -module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct +module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct type fuel = F.t type pvm_state = Context.tree - type eval_state = { - state : pvm_state; - state_hash : Sc_rollup.State_hash.t; - tick : Sc_rollup.Tick.t; - inbox_level : int32; - message_counter_offset : int; - remaining_fuel : fuel; - remaining_messages : string list; - } - - type eval_result = {state : eval_state; num_ticks : Z.t; num_messages : int} - let get_reveal ~data_dir ~pvm_kind reveal_map hash = let found_in_map = match reveal_map with | None -> None - | Some map -> Sc_rollup_reveal_hash.Map.find_opt hash map + | Some map -> + Utils.Reveal_hash_map.find_opt + (Reveals.proto_hash_to_dac_hash hash) + map in match found_in_map with | Some data -> return data @@ -427,7 +366,7 @@ module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct let eval_block_inbox ~fuel (node_ctxt : _ Node_context.t) (inbox, messages) (state : pvm_state) : - eval_result Node_context.delayed_write tzresult Lwt.t = + 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 module PVM = (val Pvm.of_kind node_ctxt.kind) in @@ -451,8 +390,8 @@ module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct let eval_state = { state; - state_hash; - tick = final_tick; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; + tick = Sc_rollup.Tick.to_z final_tick; inbox_level; message_counter_offset = num_messages; remaining_fuel; @@ -513,12 +452,13 @@ module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct messages in let*! final_tick = PVM.get_tick state in + let final_tick = Sc_rollup.Tick.to_z final_tick in let*! state_hash = PVM.state_hash state in - let num_ticks = Sc_rollup.Tick.distance initial_tick final_tick in + let num_ticks = Z.sub final_tick initial_tick in let eval_state = { state; - state_hash; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; tick = final_tick; inbox_level; message_counter_offset = message_counter_offset + num_messages; diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.ml index c4be2d729b1e6bcd36cecb450795483fc7839143..b9c436a37ca4e11d998b6869460167b92e4bf296 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.ml @@ -26,48 +26,23 @@ open Protocol open Alpha_context -(** [get_boot_sector block_hash node_ctxt] fetches the operations in the - [block_hash] and looks for the bootsector used to originate the rollup we're - following. It must be called with [block_hash.level] = - [node_ctxt.genesis_info.level]. *) let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in - let exception Found_boot_sector of string in - let* block = Layer1_helpers.fetch_tezos_block node_ctxt.l1_ctxt block_hash in - let missing_boot_sector () = - failwith "Boot sector not found in Tezos block %a" Block_hash.pp block_hash - in - Lwt.catch - (fun () -> - let apply (type kind) accu ~source:_ (operation : kind manager_operation) - (result : kind Apply_results.successful_manager_operation_result) = - match (operation, result) with - | ( Sc_rollup_originate {kind; boot_sector; _}, - Sc_rollup_originate_result {address; _} ) - when Octez_smart_rollup.Address.( - node_ctxt.rollup_address - = Sc_rollup_proto_types.Address.to_octez address) - && node_ctxt.kind = Sc_rollup_proto_types.Kind.to_octez kind -> - raise (Found_boot_sector boot_sector) - | _ -> accu - in - let apply_internal (type kind) accu ~source:_ - (_operation : kind Apply_internal_results.internal_operation) - (_result : - kind Apply_internal_results.successful_internal_operation_result) = - accu - in - let*? () = - Layer1_services.( - process_applied_manager_operations - (Ok ()) - block.operations - {apply; apply_internal}) + match node_ctxt.boot_sector_file with + | None -> Layer1_helpers.get_boot_sector block_hash node_ctxt + | Some boot_sector_file -> + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let*! boot_sector = Lwt_utils_unix.read_file boot_sector_file in + let*? boot_sector = + Option.value_e + ~error: + [ + Sc_rollup_node_errors.Unparsable_boot_sector + {path = boot_sector_file}; + ] + (PVM.parse_boot_sector boot_sector) in - missing_boot_sector ()) - (function - | Found_boot_sector boot_sector -> return boot_sector - | _ -> missing_boot_sector ()) + return boot_sector let genesis_state block_hash node_ctxt ctxt = let open Lwt_result_syntax in @@ -110,8 +85,6 @@ let transition_pvm node_ctxt ctxt predecessor Layer1.{hash = _; _} } = Delayed_write_monad.apply node_ctxt eval_result in - let state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash in - let tick = Sc_rollup.Tick.to_z tick in let module PVM = (val Pvm.of_kind node_ctxt.kind) in let*! ctxt = PVM.State.set ctxt state in let*! initial_tick = PVM.get_tick predecessor_state in @@ -177,12 +150,12 @@ let start_state_of_block node_ctxt (block : Sc_rollup_block.t) = @ [unsafe_to_string end_of_level_serialized] in return - Fueled_pvm.Accounted. + Pvm_plugin_sig. { state; - state_hash; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; inbox_level; - tick; + tick = Sc_rollup.Tick.to_z tick; message_counter_offset = 0; remaining_fuel = Fuel.Accounted.of_ticks 0L; remaining_messages = messages; @@ -193,8 +166,7 @@ let start_state_of_block node_ctxt (block : Sc_rollup_block.t) = let run_to_tick node_ctxt start_state tick = let open Delayed_write_monad.Lwt_result_syntax in let tick_distance = - Sc_rollup.Tick.distance tick start_state.Fueled_pvm.Accounted.tick - |> Z.to_int64 + Z.sub tick start_state.Pvm_plugin_sig.tick |> Z.to_int64 in let>+ eval_result = Fueled_pvm.Accounted.eval_messages @@ -208,7 +180,7 @@ let state_of_tick_aux node_ctxt ~start_state (event : Sc_rollup_block.t) tick = let* start_state = match start_state with | Some start_state - when start_state.Fueled_pvm.Accounted.inbox_level = event.header.level -> + when start_state.Pvm_plugin_sig.inbox_level = event.header.level -> return start_state | _ -> (* Recompute start state on level change or if we don't have a @@ -228,13 +200,11 @@ module Tick_state_cache = (Aches.Rache.Transfer (Aches.Rache.LRU) (struct - type t = Sc_rollup.Tick.t * Block_hash.t + type t = Z.t * Block_hash.t - let equal (t1, b1) (t2, b2) = - Sc_rollup.Tick.(t1 = t2) && Block_hash.(b1 = b2) + let equal (t1, b1) (t2, b2) = Z.equal t1 t2 && Block_hash.(b1 = b2) - let hash (tick, block) = - ((Sc_rollup.Tick.to_z tick |> Z.hash) * 13) + Block_hash.hash block + let hash (tick, block) = (Z.hash tick * 13) + Block_hash.hash block end)) let tick_state_cache = Tick_state_cache.create 64 (* size of 2 dissections *) @@ -251,16 +221,14 @@ let memo_state_of_tick_aux node_ctxt ~start_state (event : Sc_rollup_block.t) (** [state_of_tick node_ctxt ?start_state tick level] returns [Some end_state] for a given [tick] if this [tick] happened before [level]. Otherwise, returns [None].*) -let state_of_tick node_ctxt ?start_state tick level = +let state_of_tick node_ctxt ?start_state ~tick level = let open Lwt_result_syntax in let level = Raw_level.to_int32 level in - let tick = Sc_rollup.Tick.to_z tick in let* event = Node_context.block_with_tick node_ctxt ~max_level:level tick in match event with | None -> return_none | Some event -> assert (event.header.level <= level) ; - let tick = Sc_rollup.Tick.of_z tick in let* result_state = if Node_context.is_loser node_ctxt then (* TODO: https://gitlab.com/tezos/tezos/-/issues/5253 diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.mli index 124eaa96b53d4ba69484ba4dcc81688166aba0b2..acf81542788bac8866fabe73d00f89ba47fd9585 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.mli @@ -41,16 +41,16 @@ val process_head : Octez_smart_rollup.Inbox.t * string list -> ('a Context.t * int * int64 * Z.t) tzresult Lwt.t -(** [state_of_tick node_ctxt ?start_state tick level] returns [Some (state, +(** [state_of_tick node_ctxt ?start_state ~tick level] returns [Some (state, hash)] for a given [tick] if this [tick] happened before [level]. Otherwise, returns [None]. If provided, the evaluation is resumed from [start_state]. *) val state_of_tick : _ Node_context.t -> - ?start_state:Fueled_pvm.Accounted.eval_state -> - Sc_rollup.Tick.t -> + ?start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state -> + tick:Z.t -> Raw_level.t -> - Fueled_pvm.Accounted.eval_state option tzresult Lwt.t + Fuel.Accounted.t Pvm_plugin_sig.eval_state option tzresult Lwt.t (** [state_of_head node_ctxt ctxt head] returns the state corresponding to the block [head], or the state at rollup genesis if the block is before the diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.ml index 254e41b733b4ac425a75404cf4e4484a8586c61b..862f8f25eafb68066404cb788cd7c0e932a976ce 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.ml @@ -180,3 +180,43 @@ let retrieve_genesis_info cctxt rollup_address = commitment_hash = Sc_rollup_proto_types.Commitment_hash.to_octez commitment_hash; } + +let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = + let open Protocol in + let open Alpha_context in + let open Lwt_result_syntax in + let exception Found_boot_sector of string in + let* block = fetch_tezos_block node_ctxt.l1_ctxt block_hash in + let missing_boot_sector () = + failwith "Boot sector not found in Tezos block %a" Block_hash.pp block_hash + in + Lwt.catch + (fun () -> + let apply (type kind) accu ~source:_ (operation : kind manager_operation) + (result : kind Apply_results.successful_manager_operation_result) = + match (operation, result) with + | ( Sc_rollup_originate {boot_sector; _}, + Sc_rollup_originate_result {address; _} ) + when Octez_smart_rollup.Address.( + node_ctxt.rollup_address + = Sc_rollup_proto_types.Address.to_octez address) -> + raise (Found_boot_sector boot_sector) + | _ -> accu + in + let apply_internal (type kind) accu ~source:_ + (_operation : kind Apply_internal_results.internal_operation) + (_result : + kind Apply_internal_results.successful_internal_operation_result) = + accu + in + let*? () = + Layer1_services.( + process_applied_manager_operations + (Ok ()) + block.operations + {apply; apply_internal}) + in + missing_boot_sector ()) + (function + | Found_boot_sector boot_sector -> return boot_sector + | _ -> missing_boot_sector ()) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.mli index c82972f95ba0d8f23472993bc7451a0655999f68..76a3f7222957d860b9089aee96303939bcfc5de4 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.mli @@ -68,3 +68,8 @@ val retrieve_constants : val retrieve_genesis_info : #Client_context.full -> Address.t -> Node_context.genesis_info tzresult Lwt.t + +(** [get_boot_sector block_hash node_ctxt] retrieves the boot sector from the + rollup origination operation in block [block_hash]. Precondition: + [block_hash] has to be the block where the rollup was originated. *) +val get_boot_sector : Block_hash.t -> _ Node_context.t -> string tzresult Lwt.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_plugin.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_plugin.ml new file mode 100644 index 0000000000000000000000000000000000000000..fbe612a4f49f40fbe377db954ee89e39884a8ec4 --- /dev/null +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_plugin.ml @@ -0,0 +1,82 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) +open Protocol +open Alpha_context + +let get_tick kind state = + let open Lwt_syntax in + let module PVM = (val Pvm.of_kind kind) in + let+ tick = PVM.get_tick state in + Sc_rollup.Tick.to_z tick + +let state_hash kind state = + let open Lwt_syntax in + let module PVM = (val Pvm.of_kind kind) in + let+ hash = PVM.state_hash state in + Sc_rollup_proto_types.State_hash.to_octez hash + +let initial_state kind = + let module PVM = (val Pvm.of_kind kind) in + PVM.initial_state ~empty:(PVM.State.empty ()) + +let parse_boot_sector kind = + let module PVM = (val Pvm.of_kind kind) in + PVM.parse_boot_sector + +let install_boot_sector kind state boot_sector = + let module PVM = (val Pvm.of_kind kind) in + PVM.install_boot_sector state boot_sector + +let get_status node_ctxt state = + let open Lwt_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.Node_context.kind) in + let+ status = PVM.get_status state in + PVM.string_of_status status + +let get_current_level kind state = + let open Lwt_option_syntax in + let module PVM = (val Pvm.of_kind kind) in + let+ current_level = PVM.get_current_level state in + Raw_level.to_int32 current_level + +module Fueled = Fueled_pvm + +let start_of_level_serialized = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string start_of_level_serialized + +let end_of_level_serialized = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string end_of_level_serialized + +let protocol_migration_serialized = + let open Sc_rollup_inbox_message_repr in + Some (unsafe_to_string Raw_context.protocol_migration_serialized_message) + +let info_per_level_serialized ~predecessor ~predecessor_timestamp = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string + (info_per_level_serialized ~predecessor ~predecessor_timestamp) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_plugin.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_plugin.mli new file mode 100644 index 0000000000000000000000000000000000000000..e0183f81e6368cf6a620b4ec9d3c185465b832bc --- /dev/null +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_plugin.mli @@ -0,0 +1,27 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +include Pvm_plugin_sig.S diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml index 66f4dc5343909c16745f7f662f8d1a2aba9344e9..5a6b60aaa7edba6686e942031786d8c95f26597d 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml @@ -322,22 +322,26 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = type pvm_intermediate_state = | Hash of Sc_rollup.State_hash.t - | Evaluated of Fueled_pvm.Accounted.eval_state + | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok our_view = let open Lwt_result_syntax in let state_of_tick ?start_state tick = - Interpreter.state_of_tick node_ctxt ?start_state tick last_level + Interpreter.state_of_tick + node_ctxt + ?start_state + ~tick:(Sc_rollup.Tick.to_z tick) + last_level in - let state_hash_of_eval_state Fueled_pvm.Accounted.{state_hash; _} = - state_hash + let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = + Sc_rollup_proto_types.State_hash.of_octez state_hash in let start_hash, start_tick, start_state = match ok with | Hash hash, tick -> (hash, tick, None) | Evaluated ({state_hash; _} as state), tick -> - (state_hash, tick, Some state) + (Sc_rollup_proto_types.State_hash.of_octez state_hash, tick, Some state) in let start_chunk = Sc_rollup.Dissection_chunk.{state_hash = Some start_hash; tick = start_tick} @@ -345,7 +349,8 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok let our_state, our_tick = our_view in let our_state_hash = Option.map - (fun Fueled_pvm.Accounted.{state_hash; _} -> state_hash) + (fun Pvm_plugin_sig.{state_hash; _} -> + Sc_rollup_proto_types.State_hash.of_octez state_hash) our_state in let our_stop_chunk = @@ -397,7 +402,11 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent | Evaluated ok_state, _ -> Some ok_state in let* our = - Interpreter.state_of_tick node_ctxt ?start_state tick game.inbox_level + Interpreter.state_of_tick + node_ctxt + ?start_state + ~tick:(Sc_rollup.Tick.to_z tick) + game.inbox_level in match (their_hash, our) with | None, None -> @@ -406,8 +415,11 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent assert false | Some _, None | None, Some _ -> return (ok, (our, tick)) | Some their_hash, Some ({state_hash = our_hash; _} as our_state) -> - if Sc_rollup.State_hash.equal our_hash their_hash then - traverse (Evaluated our_state, tick) dissection + if + Sc_rollup.State_hash.equal + (Sc_rollup_proto_types.State_hash.of_octez our_hash) + their_hash + then traverse (Evaluated our_state, tick) dissection else return (ok, (our, tick))) in match dissection with @@ -439,7 +451,10 @@ let next_move node_ctxt ~opponent game = let open Lwt_result_syntax in let final_move start_tick = let* start_state = - Interpreter.state_of_tick node_ctxt start_tick game.inbox_level + Interpreter.state_of_tick + node_ctxt + ~tick:(Sc_rollup.Tick.to_z start_tick) + game.inbox_level in match start_state with | None -> diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/reveals.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/reveals.ml index 1a8c0a2f556473d86c4e42e0ef461bd9ef4f73bc..2430502bbf78962aa01f4d7dd8fa2486ea0404e5 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/reveals.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/reveals.ml @@ -66,6 +66,11 @@ let path data_dir pvm_name hash = let hash = Protocol.Sc_rollup_reveal_hash.to_hex hash in Filename.(concat (concat data_dir pvm_name) hash) +let proto_hash_to_dac_hash ((module Plugin) : Dac_plugin.t) proto_reveal_hash = + proto_reveal_hash + |> Data_encoding.Binary.to_bytes_exn Protocol.Sc_rollup_reveal_hash.encoding + |> Data_encoding.Binary.of_bytes_exn Plugin.encoding + let get ~data_dir ~pvm_kind ~hash = let open Lwt_result_syntax in let filename = @@ -94,3 +99,9 @@ let get ~data_dir ~pvm_kind ~hash = |> return in return contents + +let proto_hash_to_dac_hash proto_reveal_hash = + let dac_plugin = + WithExceptions.Option.get ~loc:__LOC__ @@ Dac_plugin.get Protocol.hash + in + proto_hash_to_dac_hash dac_plugin proto_reveal_hash diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/reveals.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/reveals.mli index f218cab75d38acd05a0acc9cdbd3d4e91edc3d03..53ad954bf3fe40ac17d98442db4f328c9fb2c2e7 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/reveals.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/reveals.mli @@ -71,3 +71,6 @@ val get : pvm_kind:Kind.t -> hash:Protocol.Sc_rollup_reveal_hash.t -> string tzresult Lwt.t + +(** Conversion from protocol reveal hash to protocol agnostic DAC hash. *) +val proto_hash_to_dac_hash : Protocol.Sc_rollup_reveal_hash.t -> Dac_plugin.hash diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/rollup_node_plugin.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/rollup_node_plugin.ml index 6d1642bf8f58d15e8da5aaa7e91613cda1a8d4b5..af7636f504dcbdb831999a50e1acfffc03eb3630 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/rollup_node_plugin.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/rollup_node_plugin.ml @@ -40,6 +40,8 @@ module Plugin : Protocol_plugin_sig.S = struct let process_l1_block_operations = Daemon.process_l1_block_operations end + + module Pvm = Pvm_plugin end let () = Protocol_plugins.register (module Plugin) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.ml index d557dbeb97e51c958b42fefce6686ca2a59e8d67..dd39c830ed3dfa35783dc3bac85d31f1f1a79951 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.ml @@ -38,7 +38,7 @@ type t = { ctxt : Context.ro; inbox_level : int32; state : Context.tree; - reveal_map : string Sc_rollup_reveal_hash.Map.t option; + reveal_map : string Utils.Reveal_hash_map.t option; nb_messages_inbox : int; level_position : level_position; info_per_level : info_per_level; @@ -95,11 +95,11 @@ let simulate_messages_no_checks (node_ctxt : Node_context.ro) let*! state_hash = PVM.state_hash state in let*! tick = PVM.get_tick state in let eval_state = - Fueled_pvm. + Pvm_plugin_sig. { state; - state_hash; - tick; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; + tick = Sc_rollup.Tick.to_z tick; inbox_level; message_counter_offset = nb_messages_inbox; remaining_fuel = Fuel.Free.of_ticks 0L; @@ -110,7 +110,7 @@ let simulate_messages_no_checks (node_ctxt : Node_context.ro) let* eval_result = Fueled_pvm.eval_messages ?reveal_map node_ctxt eval_state in - let Fueled_pvm.{state = {state; _}; num_ticks; num_messages; _} = + let Pvm_plugin_sig.{state = {state; _}; num_ticks; num_messages; _} = Delayed_write_monad.ignore eval_result in let*! ctxt = PVM.State.set ctxt state in diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.mli index ac8d8dd036249ecc7567d4dc7b952bd691ec4675..745ead3df5624cee2fdf4fc84c4486a0c554c18f 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.mli @@ -23,7 +23,6 @@ (* *) (*****************************************************************************) -open Protocol open Protocol.Alpha_context module Fueled_pvm = Fueled_pvm.Free @@ -39,7 +38,7 @@ type t = { ctxt : Context.ro; inbox_level : int32; state : Context.tree; - reveal_map : string Sc_rollup_reveal_hash.Map.t option; + reveal_map : string Utils.Reveal_hash_map.t option; nb_messages_inbox : int; level_position : level_position; info_per_level : info_per_level; @@ -49,7 +48,7 @@ type t = { on top} of [block], i.e. for an hypothetical new inbox (level). *) val start_simulation : Node_context.ro -> - reveal_map:string Sc_rollup_reveal_hash.Map.t option -> + reveal_map:string Utils.Reveal_hash_map.t option -> Layer1.head -> t tzresult Lwt.t diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml index 02e1beab7f409b02c811a9f286eba9a28dd6243a..4b2a455e015a7507535a0e4d590fe8796d6aa1bc 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml @@ -119,14 +119,15 @@ let simulate_messages (node_ctxt : Node_context.ro) block ~reveal_pages let reveal_map = match reveal_pages with | Some pages -> + let (module DAC_plugin) = + WithExceptions.Option.get ~loc:__LOC__ @@ Dac_plugin.get Protocol.hash + in let map = List.fold_left (fun map page -> - let hash = - Sc_rollup_reveal_hash.(hash_string ~scheme:Blake2B [page]) - in - Sc_rollup_reveal_hash.Map.add hash page map) - Sc_rollup_reveal_hash.Map.empty + let hash = DAC_plugin.hash_string ~scheme:Blake2B [page] in + Utils.Reveal_hash_map.add hash page map) + Utils.Reveal_hash_map.empty pages in Some map 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 a88e0ed416197f9d7b2958dff3d1d684980d2ddf..d0ed691d2d1f4ba75d2f1abb1cb57665c37eb6b6 100644 --- a/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml +++ b/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml @@ -26,82 +26,21 @@ open Protocol open Alpha_context module Inbox = Sc_rollup.Inbox -open Protocol -open Alpha_context - -module type S = sig - type fuel - - type pvm_state = Context.tree - - (** Evaluation state for the PVM. *) - type eval_state = { - state : pvm_state; (** The actual PVM state. *) - state_hash : Sc_rollup.State_hash.t; (** Hash of [state]. *) - tick : Sc_rollup.Tick.t; (** Tick of [state]. *) - inbox_level : int32; (** Inbox level in which messages are evaluated. *) - message_counter_offset : int; - (** Offset for message index, which corresponds to the number of - messages of the inbox already evaluated. *) - remaining_fuel : fuel; - (** Fuel remaining for the evaluation of the inbox. *) - remaining_messages : string list; - (** Messages of the inbox that remain to be evaluated. *) - } - - (** Evaluation result for the PVM which contains the evaluation state and - additional information. *) - type eval_result = {state : eval_state; num_ticks : Z.t; num_messages : int} +open Pvm_plugin_sig - (** [eval_block_inbox ~fuel node_ctxt (inbox, messages) state] evaluates the - [messages] for the [inbox] in the given [state] of the PVM and returns the - evaluation result containing the new state, the number of messages, the - inbox level and the remaining fuel. *) - val eval_block_inbox : - fuel:fuel -> - _ Node_context.t -> - Octez_smart_rollup.Inbox.t * string list -> - pvm_state -> - eval_result Node_context.delayed_write tzresult Lwt.t - - (** [eval_messages ?reveal_map ~fuel node_ctxt ~message_counter_offset state - inbox_level messages] evaluates the [messages] for inbox level - [inbox_level] in the given [state] of the PVM and returns the evaluation - results containing the new state, the remaining fuel, and the number of - ticks for the evaluation of these messages. If [messages] is empty, the - PVM progresses until the next input request (within the allocated - [fuel]). [message_counter_offset] is used when we evaluate partial - inboxes, such as during simulation. When [reveal_map] is provided, it is - used as an additional source of data for revelation ticks. *) - val eval_messages : - ?reveal_map:string Sc_rollup_reveal_hash.Map.t -> - _ Node_context.t -> - eval_state -> - eval_result Node_context.delayed_write tzresult Lwt.t -end - -module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct +module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct type fuel = F.t type pvm_state = Context.tree - type eval_state = { - state : pvm_state; - state_hash : Sc_rollup.State_hash.t; - tick : Sc_rollup.Tick.t; - inbox_level : int32; - message_counter_offset : int; - remaining_fuel : fuel; - remaining_messages : string list; - } - - type eval_result = {state : eval_state; num_ticks : Z.t; num_messages : int} - let get_reveal ~dac_client ~data_dir ~pvm_kind reveal_map hash = let found_in_map = match reveal_map with | None -> None - | Some map -> Sc_rollup_reveal_hash.Map.find_opt hash map + | Some map -> + Utils.Reveal_hash_map.find_opt + (Reveals.proto_hash_to_dac_hash hash) + map in match found_in_map with | Some data -> return data @@ -438,7 +377,7 @@ module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct let eval_block_inbox ~fuel (node_ctxt : _ Node_context.t) (inbox, messages) (state : pvm_state) : - eval_result Node_context.delayed_write tzresult Lwt.t = + 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 module PVM = (val Pvm.of_kind node_ctxt.kind) in @@ -462,8 +401,8 @@ module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct let eval_state = { state; - state_hash; - tick = final_tick; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; + tick = Sc_rollup.Tick.to_z final_tick; inbox_level; message_counter_offset = num_messages; remaining_fuel; @@ -524,12 +463,13 @@ module Make_fueled (F : Fuel.S) : S with type fuel = F.t = struct messages in let*! final_tick = PVM.get_tick state in + let final_tick = Sc_rollup.Tick.to_z final_tick in let*! state_hash = PVM.state_hash state in - let num_ticks = Sc_rollup.Tick.distance initial_tick final_tick in + let num_ticks = Z.sub final_tick initial_tick in let eval_state = { state; - state_hash; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; tick = final_tick; inbox_level; message_counter_offset = message_counter_offset + num_messages; diff --git a/src/proto_alpha/lib_sc_rollup_node/interpreter.ml b/src/proto_alpha/lib_sc_rollup_node/interpreter.ml index d4edff9d2b161f1b3a3b5a5476a35c83a1b67da8..c9c79e88f647613dc8fc8f1ac53a398588709deb 100644 --- a/src/proto_alpha/lib_sc_rollup_node/interpreter.ml +++ b/src/proto_alpha/lib_sc_rollup_node/interpreter.ml @@ -26,51 +26,10 @@ open Protocol open Alpha_context -(** [get_boot_sector block_hash node_ctxt] fetches the operations in the - [block_hash] and looks for the bootsector used to originate the rollup we're - following. It must be called with [block_hash.level] = - [node_ctxt.genesis_info.level]. *) -let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = - let open Lwt_result_syntax in - let exception Found_boot_sector of string in - let* block = Layer1_helpers.fetch_tezos_block node_ctxt.l1_ctxt block_hash in - let missing_boot_sector () = - failwith "Boot sector not found in Tezos block %a" Block_hash.pp block_hash - in - Lwt.catch - (fun () -> - let apply (type kind) accu ~source:_ (operation : kind manager_operation) - (result : kind Apply_results.successful_manager_operation_result) = - match (operation, result) with - | ( Sc_rollup_originate {kind; boot_sector; _}, - Sc_rollup_originate_result {address; _} ) - when node_ctxt.rollup_address = address - && node_ctxt.kind = Sc_rollup_proto_types.Kind.to_octez kind -> - raise (Found_boot_sector boot_sector) - | _ -> accu - in - let apply_internal (type kind) accu ~source:_ - (_operation : kind Apply_internal_results.internal_operation) - (_result : - kind Apply_internal_results.successful_internal_operation_result) = - accu - in - let*? () = - Layer1_services.( - process_applied_manager_operations - (Ok ()) - block.operations - {apply; apply_internal}) - in - missing_boot_sector ()) - (function - | Found_boot_sector boot_sector -> return boot_sector - | _ -> missing_boot_sector ()) - let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in match node_ctxt.boot_sector_file with - | None -> get_boot_sector block_hash node_ctxt + | None -> Layer1_helpers.get_boot_sector block_hash node_ctxt | Some boot_sector_file -> let module PVM = (val Pvm.of_kind node_ctxt.kind) in let*! boot_sector = Lwt_utils_unix.read_file boot_sector_file in @@ -198,12 +157,12 @@ let start_state_of_block node_ctxt (block : Sc_rollup_block.t) = @ [unsafe_to_string end_of_level_serialized] in return - Fueled_pvm.Accounted. + Pvm_plugin_sig. { state; state_hash; inbox_level; - tick; + tick = Sc_rollup.Tick.to_z tick; message_counter_offset = 0; remaining_fuel = Fuel.Accounted.of_ticks 0L; remaining_messages = messages; @@ -214,8 +173,7 @@ let start_state_of_block node_ctxt (block : Sc_rollup_block.t) = let run_to_tick node_ctxt start_state tick = let open Delayed_write_monad.Lwt_result_syntax in let tick_distance = - Sc_rollup.Tick.distance tick start_state.Fueled_pvm.Accounted.tick - |> Z.to_int64 + Z.sub tick start_state.Pvm_plugin_sig.tick |> Z.to_int64 in let>+ eval_result = Fueled_pvm.Accounted.eval_messages @@ -229,7 +187,7 @@ let state_of_tick_aux node_ctxt ~start_state (event : Sc_rollup_block.t) tick = let* start_state = match start_state with | Some start_state - when start_state.Fueled_pvm.Accounted.inbox_level = event.header.level -> + when start_state.Pvm_plugin_sig.inbox_level = event.header.level -> return start_state | _ -> (* Recompute start state on level change or if we don't have a @@ -249,13 +207,11 @@ module Tick_state_cache = (Aches.Rache.Transfer (Aches.Rache.LRU) (struct - type t = Sc_rollup.Tick.t * Block_hash.t + type t = Z.t * Block_hash.t - let equal (t1, b1) (t2, b2) = - Sc_rollup.Tick.(t1 = t2) && Block_hash.(b1 = b2) + let equal (t1, b1) (t2, b2) = Z.equal t1 t2 && Block_hash.(b1 = b2) - let hash (tick, block) = - ((Sc_rollup.Tick.to_z tick |> Z.hash) * 13) + Block_hash.hash block + let hash (tick, block) = (Z.hash tick * 13) + Block_hash.hash block end)) let tick_state_cache = Tick_state_cache.create 64 (* size of 2 dissections *) @@ -272,16 +228,14 @@ let memo_state_of_tick_aux node_ctxt ~start_state (event : Sc_rollup_block.t) (** [state_of_tick node_ctxt ?start_state tick level] returns [Some end_state] for a given [tick] if this [tick] happened before [level]. Otherwise, returns [None].*) -let state_of_tick node_ctxt ?start_state tick level = +let state_of_tick node_ctxt ?start_state ~tick level = let open Lwt_result_syntax in let level = Raw_level.to_int32 level in - let tick = Sc_rollup.Tick.to_z tick in let* event = Node_context.block_with_tick node_ctxt ~max_level:level tick in match event with | None -> return_none | Some event -> assert (event.header.level <= level) ; - let tick = Sc_rollup.Tick.of_z tick in let* result_state = if Node_context.is_loser node_ctxt then (* TODO: https://gitlab.com/tezos/tezos/-/issues/5253 diff --git a/src/proto_alpha/lib_sc_rollup_node/interpreter.mli b/src/proto_alpha/lib_sc_rollup_node/interpreter.mli index 124eaa96b53d4ba69484ba4dcc81688166aba0b2..acf81542788bac8866fabe73d00f89ba47fd9585 100644 --- a/src/proto_alpha/lib_sc_rollup_node/interpreter.mli +++ b/src/proto_alpha/lib_sc_rollup_node/interpreter.mli @@ -41,16 +41,16 @@ val process_head : Octez_smart_rollup.Inbox.t * string list -> ('a Context.t * int * int64 * Z.t) tzresult Lwt.t -(** [state_of_tick node_ctxt ?start_state tick level] returns [Some (state, +(** [state_of_tick node_ctxt ?start_state ~tick level] returns [Some (state, hash)] for a given [tick] if this [tick] happened before [level]. Otherwise, returns [None]. If provided, the evaluation is resumed from [start_state]. *) val state_of_tick : _ Node_context.t -> - ?start_state:Fueled_pvm.Accounted.eval_state -> - Sc_rollup.Tick.t -> + ?start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state -> + tick:Z.t -> Raw_level.t -> - Fueled_pvm.Accounted.eval_state option tzresult Lwt.t + Fuel.Accounted.t Pvm_plugin_sig.eval_state option tzresult Lwt.t (** [state_of_head node_ctxt ctxt head] returns the state corresponding to the block [head], or the state at rollup genesis if the block is before the diff --git a/src/proto_alpha/lib_sc_rollup_node/interpreter_event.ml b/src/proto_alpha/lib_sc_rollup_node/interpreter_event.ml index ff8f435c5f35b7445d4e4af46fbf231934455fda..3eeb93d6b531a4f50ab2c38504c62602d5d863cc 100644 --- a/src/proto_alpha/lib_sc_rollup_node/interpreter_event.ml +++ b/src/proto_alpha/lib_sc_rollup_node/interpreter_event.ml @@ -23,8 +23,6 @@ (* *) (*****************************************************************************) -open Protocol.Alpha_context.Sc_rollup - module Simple = struct include Internal_event.Simple @@ -40,7 +38,7 @@ module Simple = struct ~level:Notice ("inbox_level", Data_encoding.int32) ("state_hash", Octez_smart_rollup.State_hash.encoding) - ("ticks", Tick.encoding) + ("ticks", Data_encoding.z) ("num_messages", Data_encoding.int31) let intended_failure = diff --git a/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.ml b/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.ml index b2e0c93631770c05d1c92d02d71c7852693e0b57..011004110d24efcafa0774cd5c31831edc27cf35 100644 --- a/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.ml +++ b/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.ml @@ -186,3 +186,41 @@ let retrieve_genesis_info cctxt rollup_address = commitment_hash = Sc_rollup_proto_types.Commitment_hash.to_octez commitment_hash; } + +let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = + let open Protocol in + let open Alpha_context in + let open Lwt_result_syntax in + let exception Found_boot_sector of string in + let* block = fetch_tezos_block node_ctxt.l1_ctxt block_hash in + let missing_boot_sector () = + failwith "Boot sector not found in Tezos block %a" Block_hash.pp block_hash + in + Lwt.catch + (fun () -> + let apply (type kind) accu ~source:_ (operation : kind manager_operation) + (result : kind Apply_results.successful_manager_operation_result) = + match (operation, result) with + | ( Sc_rollup_originate {boot_sector; _}, + Sc_rollup_originate_result {address; _} ) + when node_ctxt.rollup_address = address -> + raise (Found_boot_sector boot_sector) + | _ -> accu + in + let apply_internal (type kind) accu ~source:_ + (_operation : kind Apply_internal_results.internal_operation) + (_result : + kind Apply_internal_results.successful_internal_operation_result) = + accu + in + let*? () = + Layer1_services.( + process_applied_manager_operations + (Ok ()) + block.operations + {apply; apply_internal}) + in + missing_boot_sector ()) + (function + | Found_boot_sector boot_sector -> return boot_sector + | _ -> missing_boot_sector ()) diff --git a/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.mli b/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.mli index c82972f95ba0d8f23472993bc7451a0655999f68..76a3f7222957d860b9089aee96303939bcfc5de4 100644 --- a/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.mli +++ b/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.mli @@ -68,3 +68,8 @@ val retrieve_constants : val retrieve_genesis_info : #Client_context.full -> Address.t -> Node_context.genesis_info tzresult Lwt.t + +(** [get_boot_sector block_hash node_ctxt] retrieves the boot sector from the + rollup origination operation in block [block_hash]. Precondition: + [block_hash] has to be the block where the rollup was originated. *) +val get_boot_sector : Block_hash.t -> _ Node_context.t -> string tzresult Lwt.t diff --git a/src/proto_alpha/lib_sc_rollup_node/pvm_plugin.ml b/src/proto_alpha/lib_sc_rollup_node/pvm_plugin.ml new file mode 100644 index 0000000000000000000000000000000000000000..650d061611553abf46e2d887258f0417498e2c90 --- /dev/null +++ b/src/proto_alpha/lib_sc_rollup_node/pvm_plugin.ml @@ -0,0 +1,90 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) +open Protocol +open Alpha_context + +let get_tick kind state = + let open Lwt_syntax in + let module PVM = (val Pvm.of_kind kind) in + let+ tick = PVM.get_tick state in + Sc_rollup.Tick.to_z tick + +let state_hash kind state = + let open Lwt_syntax in + let module PVM = (val Pvm.of_kind kind) in + let+ hash = PVM.state_hash state in + Sc_rollup_proto_types.State_hash.to_octez hash + +let initial_state kind = + let module PVM = (val Pvm.of_kind kind) in + PVM.initial_state ~empty:(PVM.State.empty ()) + +let parse_boot_sector kind = + let module PVM = (val Pvm.of_kind kind) in + PVM.parse_boot_sector + +let install_boot_sector kind state boot_sector = + let module PVM = (val Pvm.of_kind kind) in + PVM.install_boot_sector state boot_sector + +let get_status (node_ctxt : _ Node_context.t) state = + let open Lwt_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5871 + Use constants for correct protocol. *) + let is_reveal_enabled = + node_ctxt.current_protocol.constants.sc_rollup.reveal_activation_level + |> WithExceptions.Option.get ~loc:__LOC__ + |> Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez + |> Protocol.Alpha_context.Sc_rollup.is_reveal_enabled_predicate + in + let+ status = PVM.get_status ~is_reveal_enabled state in + PVM.string_of_status status + +let get_current_level kind state = + let open Lwt_option_syntax in + let module PVM = (val Pvm.of_kind kind) in + let+ current_level = PVM.get_current_level state in + Raw_level.to_int32 current_level + +module Fueled = Fueled_pvm + +let start_of_level_serialized = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string start_of_level_serialized + +let end_of_level_serialized = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string end_of_level_serialized + +let protocol_migration_serialized = + let open Sc_rollup_inbox_message_repr in + Some (unsafe_to_string Raw_context.protocol_migration_serialized_message) + +let info_per_level_serialized ~predecessor ~predecessor_timestamp = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string + (info_per_level_serialized ~predecessor ~predecessor_timestamp) diff --git a/src/proto_alpha/lib_sc_rollup_node/pvm_plugin.mli b/src/proto_alpha/lib_sc_rollup_node/pvm_plugin.mli new file mode 100644 index 0000000000000000000000000000000000000000..e0183f81e6368cf6a620b4ec9d3c185465b832bc --- /dev/null +++ b/src/proto_alpha/lib_sc_rollup_node/pvm_plugin.mli @@ -0,0 +1,27 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +include Pvm_plugin_sig.S diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml index 908b37937384a61761666b51189623abdce4fce9..afabcca77936d54bb0b48f2f31a0b16397bbffad 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml @@ -333,17 +333,19 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = type pvm_intermediate_state = | Hash of Sc_rollup.State_hash.t - | Evaluated of Fueled_pvm.Accounted.eval_state + | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok our_view = let open Lwt_result_syntax in let state_of_tick ?start_state tick = - Interpreter.state_of_tick node_ctxt ?start_state tick last_level - in - let state_hash_of_eval_state Fueled_pvm.Accounted.{state_hash; _} = - state_hash + Interpreter.state_of_tick + node_ctxt + ?start_state + ~tick:(Sc_rollup.Tick.to_z tick) + last_level in + let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = state_hash in let start_hash, start_tick, start_state = match ok with | Hash hash, tick -> (hash, tick, None) @@ -355,9 +357,7 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok in let our_state, our_tick = our_view in let our_state_hash = - Option.map - (fun Fueled_pvm.Accounted.{state_hash; _} -> state_hash) - our_state + Option.map (fun Pvm_plugin_sig.{state_hash; _} -> state_hash) our_state in let our_stop_chunk = Sc_rollup.Dissection_chunk.{state_hash = our_state_hash; tick = our_tick} @@ -408,7 +408,11 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent | Evaluated ok_state, _ -> Some ok_state in let* our = - Interpreter.state_of_tick node_ctxt ?start_state tick game.inbox_level + Interpreter.state_of_tick + node_ctxt + ?start_state + ~tick:(Sc_rollup.Tick.to_z tick) + game.inbox_level in match (their_hash, our) with | None, None -> @@ -450,7 +454,10 @@ let next_move node_ctxt ~opponent game = let open Lwt_result_syntax in let final_move start_tick = let* start_state = - Interpreter.state_of_tick node_ctxt start_tick game.inbox_level + Interpreter.state_of_tick + node_ctxt + ~tick:(Sc_rollup.Tick.to_z start_tick) + game.inbox_level in match start_state with | None -> diff --git a/src/proto_alpha/lib_sc_rollup_node/reveals.ml b/src/proto_alpha/lib_sc_rollup_node/reveals.ml index 6e1be53beb93205d359573e5ddf14408f01229b0..ee9001ba0c043b970fbb27237477d01dfe5da0c4 100644 --- a/src/proto_alpha/lib_sc_rollup_node/reveals.ml +++ b/src/proto_alpha/lib_sc_rollup_node/reveals.ml @@ -113,3 +113,9 @@ let get ~dac_client ~data_dir ~pvm_kind hash = |> return in return contents + +let proto_hash_to_dac_hash proto_reveal_hash = + let dac_plugin = + WithExceptions.Option.get ~loc:__LOC__ @@ Dac_plugin.get Protocol.hash + in + proto_hash_to_dac_hash dac_plugin proto_reveal_hash diff --git a/src/proto_alpha/lib_sc_rollup_node/reveals.mli b/src/proto_alpha/lib_sc_rollup_node/reveals.mli index def199a79b32e7c279743417c5402c3adca8f80a..53e19982711219ef4c5ef04d583c363e9d030e08 100644 --- a/src/proto_alpha/lib_sc_rollup_node/reveals.mli +++ b/src/proto_alpha/lib_sc_rollup_node/reveals.mli @@ -73,3 +73,6 @@ val get : pvm_kind:Kind.t -> Protocol.Sc_rollup_reveal_hash.t -> string tzresult Lwt.t + +(** Conversion from protocol reveal hash to protocol agnostic DAC hash. *) +val proto_hash_to_dac_hash : Protocol.Sc_rollup_reveal_hash.t -> Dac_plugin.hash diff --git a/src/proto_alpha/lib_sc_rollup_node/rollup_node_plugin.ml b/src/proto_alpha/lib_sc_rollup_node/rollup_node_plugin.ml index 6d1642bf8f58d15e8da5aaa7e91613cda1a8d4b5..af7636f504dcbdb831999a50e1acfffc03eb3630 100644 --- a/src/proto_alpha/lib_sc_rollup_node/rollup_node_plugin.ml +++ b/src/proto_alpha/lib_sc_rollup_node/rollup_node_plugin.ml @@ -40,6 +40,8 @@ module Plugin : Protocol_plugin_sig.S = struct let process_l1_block_operations = Daemon.process_l1_block_operations end + + module Pvm = Pvm_plugin end let () = Protocol_plugins.register (module Plugin) diff --git a/src/proto_alpha/lib_sc_rollup_node/simulation.ml b/src/proto_alpha/lib_sc_rollup_node/simulation.ml index d557dbeb97e51c958b42fefce6686ca2a59e8d67..dd39c830ed3dfa35783dc3bac85d31f1f1a79951 100644 --- a/src/proto_alpha/lib_sc_rollup_node/simulation.ml +++ b/src/proto_alpha/lib_sc_rollup_node/simulation.ml @@ -38,7 +38,7 @@ type t = { ctxt : Context.ro; inbox_level : int32; state : Context.tree; - reveal_map : string Sc_rollup_reveal_hash.Map.t option; + reveal_map : string Utils.Reveal_hash_map.t option; nb_messages_inbox : int; level_position : level_position; info_per_level : info_per_level; @@ -95,11 +95,11 @@ let simulate_messages_no_checks (node_ctxt : Node_context.ro) let*! state_hash = PVM.state_hash state in let*! tick = PVM.get_tick state in let eval_state = - Fueled_pvm. + Pvm_plugin_sig. { state; - state_hash; - tick; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; + tick = Sc_rollup.Tick.to_z tick; inbox_level; message_counter_offset = nb_messages_inbox; remaining_fuel = Fuel.Free.of_ticks 0L; @@ -110,7 +110,7 @@ let simulate_messages_no_checks (node_ctxt : Node_context.ro) let* eval_result = Fueled_pvm.eval_messages ?reveal_map node_ctxt eval_state in - let Fueled_pvm.{state = {state; _}; num_ticks; num_messages; _} = + let Pvm_plugin_sig.{state = {state; _}; num_ticks; num_messages; _} = Delayed_write_monad.ignore eval_result in let*! ctxt = PVM.State.set ctxt state in diff --git a/src/proto_alpha/lib_sc_rollup_node/simulation.mli b/src/proto_alpha/lib_sc_rollup_node/simulation.mli index ac8d8dd036249ecc7567d4dc7b952bd691ec4675..745ead3df5624cee2fdf4fc84c4486a0c554c18f 100644 --- a/src/proto_alpha/lib_sc_rollup_node/simulation.mli +++ b/src/proto_alpha/lib_sc_rollup_node/simulation.mli @@ -23,7 +23,6 @@ (* *) (*****************************************************************************) -open Protocol open Protocol.Alpha_context module Fueled_pvm = Fueled_pvm.Free @@ -39,7 +38,7 @@ type t = { ctxt : Context.ro; inbox_level : int32; state : Context.tree; - reveal_map : string Sc_rollup_reveal_hash.Map.t option; + reveal_map : string Utils.Reveal_hash_map.t option; nb_messages_inbox : int; level_position : level_position; info_per_level : info_per_level; @@ -49,7 +48,7 @@ type t = { on top} of [block], i.e. for an hypothetical new inbox (level). *) val start_simulation : Node_context.ro -> - reveal_map:string Sc_rollup_reveal_hash.Map.t option -> + reveal_map:string Utils.Reveal_hash_map.t option -> Layer1.head -> t tzresult Lwt.t