package octez-smart-rollup-node-lib

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file protocol_plugins.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
(*****************************************************************************)
(*                                                                           *)
(* Open Source License                                                       *)
(* Copyright (c) 2023 Functori, <contact@functori.com>                       *)
(*                                                                           *)
(* 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 error += Unsupported_protocol of Protocol_hash.t

let () =
  register_error_kind
    ~id:"smart_rollup.node.unsupported_protocol"
    ~title:"Protocol not supported by rollup node"
    ~description:"Protocol not supported by rollup node."
    ~pp:(fun ppf proto ->
      Format.fprintf
        ppf
        "Protocol %a is not supported by the rollup node."
        Protocol_hash.pp
        proto)
    `Permanent
    Data_encoding.(obj1 (req "protocol" Protocol_hash.encoding))
    (function Unsupported_protocol p -> Some p | _ -> None)
    (fun p -> Unsupported_protocol p)

type proto_plugin = (module Protocol_plugin_sig.S)

let proto_plugins : proto_plugin Protocol_hash.Table.t =
  Protocol_hash.Table.create 7

let last_registered = ref None

let register (plugin : proto_plugin) =
  let module Plugin = (val plugin) in
  if Protocol_hash.Table.mem proto_plugins Plugin.protocol then
    Format.kasprintf
      invalid_arg
      "The rollup node protocol plugin for protocol %a is already registered. \
       Did you register it manually multiple times?"
      Protocol_hash.pp
      Plugin.protocol ;
  last_registered := Some 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 last_registered () =
  match !last_registered with
  | None -> Stdlib.failwith "No protocol plugins registered"
  | Some p -> p

let proto_plugin_for_protocol protocol =
  Protocol_hash.Table.find proto_plugins protocol
  |> Option.to_result ~none:[Unsupported_protocol protocol]

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_level_with_store node_store level =
  let open Lwt_result_syntax in
  let* {protocol; _} =
    Node_context.protocol_of_level_with_store node_store 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_opt node_ctxt =
  let open Lwt_result_syntax in
  let* protocol = Node_context.last_seen_protocol node_ctxt in
  match protocol with
  | None -> return_none
  | Some protocol ->
      let*? plugin = proto_plugin_for_protocol protocol in
      return_some plugin

let last_proto_plugin node_ctxt =
  let open Lwt_result_syntax in
  let* plugin = last_proto_plugin_opt node_ctxt in
  match plugin with
  | None -> failwith "No known last protocol, cannot get plugin"
  | Some plugin -> return plugin

module Constants_cache =
  Aches_lwt.Lache.Make_result
    (Aches.Rache.Transfer (Aches.Rache.LRU) (Protocol_hash))

let constants_cache =
  let cache_size = 3 in
  Constants_cache.create cache_size

let get_constants_of_protocol ?level (node_ctxt : _ Node_context.t)
    protocol_hash =
  let open Lwt_result_syntax in
  let current_protocol = Reference.get node_ctxt.current_protocol in
  if Protocol_hash.(protocol_hash = current_protocol.hash) then
    return current_protocol.constants
  else
    let retrieve protocol_hash =
      let*? plugin = proto_plugin_for_protocol protocol_hash in
      let module Plugin = (val plugin) in
      let* level =
        match level with
        | None ->
            let+ (First_known l | Activation_level l) =
              Node_context.protocol_activation_level node_ctxt protocol_hash
            in
            l
        | Some l ->
            (* If the head is the last block of the protocol, i.e. a migration
               block, we need to use its predecessor to fetch constants from the
               correct context. For the other cases, the context of the
               predecessor is always the same protocol. *)
            return (Int32.pred l)
      in
      Plugin.Layer1_helpers.retrieve_constants
        ~block:(`Level level)
        node_ctxt.cctxt
    in
    Constants_cache.bind_or_put
      constants_cache
      protocol_hash
      retrieve
      Lwt.return

let get_constants_of_level node_ctxt level =
  let open Lwt_result_syntax in
  let* {protocol; _} = Node_context.protocol_of_level node_ctxt level in
  get_constants_of_protocol ~level node_ctxt protocol

let get_constants_of_block_hash node_ctxt block_hash =
  let open Lwt_result_syntax in
  let* level = Node_context.level_of_hash node_ctxt block_hash in
  get_constants_of_level node_ctxt level
OCaml

Innovation. Community. Security.