From fc56e84706b348b9cafdfac0a63a752287c7baad Mon Sep 17 00:00:00 2001 From: Antonio Locascio Date: Tue, 21 Feb 2023 15:24:03 +0100 Subject: [PATCH 1/2] SCORU/Node: introduce Reference abstraction with type-level r/w information --- .../lib_sc_rollup_node/reference.ml | 38 +++++++++++++++ .../lib_sc_rollup_node/reference.mli | 48 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/proto_alpha/lib_sc_rollup_node/reference.ml create mode 100644 src/proto_alpha/lib_sc_rollup_node/reference.mli diff --git a/src/proto_alpha/lib_sc_rollup_node/reference.ml b/src/proto_alpha/lib_sc_rollup_node/reference.ml new file mode 100644 index 000000000000..abb57b197bdb --- /dev/null +++ b/src/proto_alpha/lib_sc_rollup_node/reference.ml @@ -0,0 +1,38 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +type ('perm, 'value) t = 'value ref + +type 'a rw = ([`Read | `Write], 'a) t + +type 'a ro = ([`Read], 'a) t + +let get r = !r + +let set r v = r := v + +let new_ v = ref v + +let readonly r = r diff --git a/src/proto_alpha/lib_sc_rollup_node/reference.mli b/src/proto_alpha/lib_sc_rollup_node/reference.mli new file mode 100644 index 000000000000..04821bff4834 --- /dev/null +++ b/src/proto_alpha/lib_sc_rollup_node/reference.mli @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +(** Abstraction module for OCaml references *) + +(** Type [('perm, 'value) t] represents references containing a value + of type ['value] and permissions specified by ['perm]. *) +type ('perm, 'value) t + +(** Read/write reference {!t}. *) +type 'a rw = ([`Read | `Write], 'a) t + +(** Read only reference {!t}. *) +type 'a ro = ([`Read], 'a) t + +(** [get r] returns the value held by reference [r]. *) +val get : (_, 'a) t -> 'a + +(** [set r v] sets reference [r] to the value [v]. *) +val set : 'a rw -> 'a -> unit + +(** [new_ v] creates a fresh reference holding value [v]. *) +val new_ : 'a -> (_, 'a) t + +(** [readonly r] casts reference [r] to be read only. *) +val readonly : (_, 'a) t -> 'a ro -- GitLab From 120a87fdfad5fec7779d00a1b6bd711d79f8611e Mon Sep 17 00:00:00 2001 From: Antonio Locascio Date: Tue, 21 Feb 2023 15:25:04 +0100 Subject: [PATCH 2/2] SCORU/Node: use Reference abstraction for node context mutable fields --- .../lib_sc_rollup_node/RPC_directory_helpers.ml | 3 ++- .../lib_sc_rollup_node/RPC_server.ml | 7 ++++--- .../lib_sc_rollup_node/commitment.ml | 17 +++++++++-------- src/proto_alpha/lib_sc_rollup_node/daemon.ml | 9 +++++---- .../lib_sc_rollup_node/node_context.ml | 10 ++++++---- .../lib_sc_rollup_node/node_context.mli | 4 ++-- src/proto_alpha/lib_sc_rollup_node/outbox.ml | 8 ++++---- 7 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_directory_helpers.ml b/src/proto_alpha/lib_sc_rollup_node/RPC_directory_helpers.ml index 9e0cbc672586..ca7cf1e405fa 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_directory_helpers.ml +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_directory_helpers.ml @@ -82,9 +82,10 @@ module Block_directory_helpers = struct let get_last_cemented (node_ctxt : _ Node_context.t) = protect @@ fun () -> + let lcc = Reference.get node_ctxt.lcc in Node_context.hash_of_level node_ctxt - (Alpha_context.Raw_level.to_int32 node_ctxt.lcc.level) + (Alpha_context.Raw_level.to_int32 lcc.level) let block_of_prefix node_ctxt block = match block with diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_server.ml b/src/proto_alpha/lib_sc_rollup_node/RPC_server.ml index 31d984970188..75c9717b4cf0 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_server.ml +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_server.ml @@ -270,7 +270,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct Local_directory.register0 Sc_rollup_services.Local.last_published_commitment @@ fun node_ctxt () () -> let open Lwt_result_syntax in - match node_ctxt.lpc with + match Reference.get node_ctxt.lpc with | None -> return_none | Some commitment -> let hash = @@ -357,7 +357,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct = let open Alpha_context in let open Option_syntax in - let+ last_published_commitment = node_ctxt.lpc in + let+ last_published_commitment = Reference.get node_ctxt.lpc in let commitment_period = Int32.of_int node_ctxt.protocol_constants.parametric.sc_rollup @@ -380,8 +380,9 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct | Some {header = {level = finalized_level; _}; _} -> Compare.Int32.(inbox_level <= Raw_level.to_int32 finalized_level) in + let lcc = Reference.get node_ctxt.lcc in let cemented = - Compare.Int32.(inbox_level <= Raw_level.to_int32 node_ctxt.lcc.level) + Compare.Int32.(inbox_level <= Raw_level.to_int32 lcc.level) in Sc_rollup_services.{finalized; cemented} diff --git a/src/proto_alpha/lib_sc_rollup_node/commitment.ml b/src/proto_alpha/lib_sc_rollup_node/commitment.ml index cf661f32afa6..465348acaa0f 100644 --- a/src/proto_alpha/lib_sc_rollup_node/commitment.ml +++ b/src/proto_alpha/lib_sc_rollup_node/commitment.ml @@ -184,7 +184,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let missing_commitments (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in let lpc_level = - match node_ctxt.lpc with + match Reference.get node_ctxt.lpc with | None -> node_ctxt.genesis_info.level | Some lpc -> lpc.inbox_level in @@ -201,10 +201,10 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let* commitment = Node_context.find_commitment node_ctxt commitment_hash in + let lcc = Reference.get node_ctxt.lcc in match commitment with | None -> return acc - | Some commitment - when Raw_level.(commitment.inbox_level <= node_ctxt.lcc.level) -> + | Some commitment when Raw_level.(commitment.inbox_level <= lcc.level) -> (* Commitment is before or at the LCC, we have reached the end. *) return acc | Some commitment when Raw_level.(commitment.inbox_level <= lpc_level) -> @@ -271,12 +271,13 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct = let open Lwt_result_syntax in let operator = Node_context.get_operator node_ctxt Publish in + let lcc = Reference.get node_ctxt.lcc in match operator with | None -> (* Configured to not publish commitments *) return_unit | Some source -> - when_ (commitment.inbox_level > node_ctxt.lcc.level) @@ fun () -> + when_ (commitment.inbox_level > lcc.level) @@ fun () -> publish_commitment node_ctxt ~source commitment (* Commitments can only be cemented after [sc_rollup_challenge_window] has @@ -306,8 +307,8 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct return @@ sub_level commitment.inbox_level (sc_rollup_challenge_window node_ctxt) in - if Raw_level.(cementable_level_bound <= node_ctxt.lcc.level) then - return_none + let lcc = Reference.get node_ctxt.lcc in + if Raw_level.(cementable_level_bound <= lcc.level) then return_none else let** cementable_bound_block = Node_context.find_l2_block_by_level @@ -324,14 +325,14 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let open Lwt_result_option_list_syntax in let*& head = Node_context.last_processed_head_opt node_ctxt in let head_level = head.header.level in + let lcc = Reference.get node_ctxt.lcc in let rec gather acc (commitment_hash : Sc_rollup.Commitment.Hash.t) = let* commitment = Node_context.find_commitment node_ctxt commitment_hash in match commitment with | None -> return acc - | Some commitment - when Raw_level.(commitment.inbox_level <= node_ctxt.lcc.level) -> + | Some commitment when Raw_level.(commitment.inbox_level <= lcc.level) -> (* If we have moved backward passed or at the current LCC then we have reached the end. *) return acc diff --git a/src/proto_alpha/lib_sc_rollup_node/daemon.ml b/src/proto_alpha/lib_sc_rollup_node/daemon.ml index df40af7784fa..9eec68ad2ebd 100644 --- a/src/proto_alpha/lib_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/lib_sc_rollup_node/daemon.ml @@ -92,11 +92,11 @@ module Make (PVM : Pvm.S) = struct when Node_context.is_operator node_ctxt source -> (* Published commitment --------------------------------------------- *) let save_lpc = - match node_ctxt.lpc with + match Reference.get node_ctxt.lpc with | None -> true | Some lpc -> Raw_level.(commitment.inbox_level >= lpc.inbox_level) in - if save_lpc then node_ctxt.lpc <- Some commitment ; + if save_lpc then Reference.set node_ctxt.lpc (Some commitment) ; let commitment_hash = Sc_rollup.Commitment.hash_uncarbonated commitment in @@ -171,9 +171,10 @@ module Make (PVM : Pvm.S) = struct on_l1 = commitment; }) in + let lcc = Reference.get node_ctxt.lcc in let*! () = - if Raw_level.(inbox_level > node_ctxt.lcc.level) then ( - node_ctxt.lcc <- {commitment; level = inbox_level} ; + if Raw_level.(inbox_level > lcc.level) then ( + Reference.set node_ctxt.lcc {commitment; level = inbox_level} ; Commitment_event.last_cemented_commitment_updated commitment inbox_level) diff --git a/src/proto_alpha/lib_sc_rollup_node/node_context.ml b/src/proto_alpha/lib_sc_rollup_node/node_context.ml index ff82c829aa61..0009bf09b4b1 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.ml @@ -47,8 +47,8 @@ type 'a t = { loser_mode : Loser_mode.t; store : 'a store; context : 'a Context.index; - mutable lcc : lcc; - mutable lpc : Sc_rollup.Commitment.t option; + lcc : ('a, lcc) Reference.t; + lpc : ('a, Sc_rollup.Commitment.t option) Reference.t; } type rw = [`Read | `Write] t @@ -163,8 +163,8 @@ let init (cctxt : Protocol_client_context.full) ~data_dir mode mode = operating_mode; operators; genesis_info = l1_ctxt.Layer1.genesis_info; - lcc; - lpc; + lcc = Reference.new_ lcc; + lpc = Reference.new_ lpc; kind; injector_retention_period = 0; block_finality_time = 2; @@ -219,6 +219,8 @@ let readonly (node_ctxt : _ t) = node_ctxt with store = Store.readonly node_ctxt.store; context = Context.readonly node_ctxt.context; + lcc = Reference.readonly node_ctxt.lcc; + lpc = Reference.readonly node_ctxt.lpc; } type 'a delayed_write = ('a, rw) Delayed_write_monad.t diff --git a/src/proto_alpha/lib_sc_rollup_node/node_context.mli b/src/proto_alpha/lib_sc_rollup_node/node_context.mli index f616c50fe533..82fc45f6a887 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.mli +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.mli @@ -65,8 +65,8 @@ type 'a t = { store : 'a store; (** The store for the persistent storage. *) context : 'a Context.index; (** The persistent context for the rollup node. *) - mutable lcc : lcc; (** Last cemented commitment and its level. *) - mutable lpc : Sc_rollup.Commitment.t option; + lcc : ('a, lcc) Reference.t; (** Last cemented commitment and its level. *) + lpc : ('a, Sc_rollup.Commitment.t option) Reference.t; (** The last published commitment, i.e. commitment that the operator is staked on. *) } diff --git a/src/proto_alpha/lib_sc_rollup_node/outbox.ml b/src/proto_alpha/lib_sc_rollup_node/outbox.ml index 66a5a55a2425..8b539af74ef6 100644 --- a/src/proto_alpha/lib_sc_rollup_node/outbox.ml +++ b/src/proto_alpha/lib_sc_rollup_node/outbox.ml @@ -29,10 +29,9 @@ open Protocol.Alpha_context module Make (PVM : Pvm.S) = struct let get_state_of_lcc node_ctxt = let open Lwt_result_syntax in + let lcc = Reference.get node_ctxt.lcc in let* block_hash = - Node_context.hash_of_level - node_ctxt - (Raw_level.to_int32 node_ctxt.lcc.level) + Node_context.hash_of_level node_ctxt (Raw_level.to_int32 lcc.level) in let* ctxt = Node_context.checkout_context node_ctxt block_hash in let*! state = PVM.State.find ctxt in @@ -41,6 +40,7 @@ module Make (PVM : Pvm.S) = struct let proof_of_output node_ctxt output = let open Lwt_result_syntax in let* state = get_state_of_lcc node_ctxt in + let lcc = Reference.get node_ctxt.lcc in match state with | None -> (* @@ -55,7 +55,7 @@ module Make (PVM : Pvm.S) = struct let serialized_proof = Data_encoding.Binary.to_string_exn PVM.output_proof_encoding proof in - return @@ (node_ctxt.lcc.commitment, serialized_proof) + return @@ (lcc.commitment, serialized_proof) | Error err -> failwith "Error producing outbox proof (%a)" -- GitLab