• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MinaProtocol / mina / 2863

05 Nov 2024 06:20PM UTC coverage: 30.754% (-16.6%) from 47.311%
2863

push

buildkite

web-flow
Merge pull request #16296 from MinaProtocol/dkijania/more_multi_jobs

more multi jobs in CI

20276 of 65930 relevant lines covered (30.75%)

8631.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.87
/src/lib/transition_handler/validator.ml
1
open Async_kernel
1✔
2
open Core_kernel
3
open Pipe_lib.Strict_pipe
4
open Mina_base
5
open Mina_state
6
open Cache_lib
7
open Mina_block
8
open Network_peer
9

10
module type CONTEXT = sig
11
  val logger : Logger.t
12

13
  val precomputed_values : Precomputed_values.t
14

15
  val constraint_constants : Genesis_constants.Constraint_constants.t
16

17
  val consensus_constants : Consensus.Constants.t
18
end
19

20
let validate_transition_is_relevant ~context:(module Context : CONTEXT)
21
    ~frontier ~unprocessed_transition_cache ~slot_tx_end ~slot_chain_end
22
    enveloped_transition =
23
  let logger = Context.logger in
×
24
  let open Result.Let_syntax in
25
  let transition =
26
    Envelope.Incoming.data enveloped_transition
×
27
    |> Mina_block.Validation.block_with_hash
28
  in
29
  let transition_hash = State_hash.With_state_hashes.state_hash transition in
×
30
  [%log internal] "Validate_transition" ;
×
31
  let root_breadcrumb = Transition_frontier.root frontier in
×
32
  let transition_data = With_hash.data transition in
×
33
  let block_slot =
×
34
    Consensus.Data.Consensus_state.curr_global_slot
35
    @@ Protocol_state.consensus_state @@ Header.protocol_state
×
36
    @@ Mina_block.header transition_data
×
37
  in
38
  let%bind () =
39
    match slot_chain_end with
40
    | Some slot_chain_end
×
41
      when Mina_numbers.Global_slot_since_hard_fork.(
42
             block_slot >= slot_chain_end) ->
43
        [%log info] "Block after slot_chain_end, rejecting" ;
×
44
        Result.fail `Block_after_after_stop_slot
×
45
    | None | Some _ ->
×
46
        Result.return ()
×
47
  in
48
  let%bind () =
49
    match slot_tx_end with
50
    | Some slot_tx_end
×
51
      when Mina_numbers.Global_slot_since_hard_fork.(block_slot >= slot_tx_end)
52
      ->
53
        [%log info] "Block after slot_tx_end, validating it is empty" ;
×
54
        let staged_ledger_diff =
×
55
          Body.staged_ledger_diff @@ body transition_data
×
56
        in
57
        Result.ok_if_true
×
58
          ( Staged_ledger_diff.compare Staged_ledger_diff.empty_diff
×
59
              staged_ledger_diff
60
          = 0 )
61
          ~error:`Non_empty_staged_ledger_diff_after_stop_slot
62
    | None | Some _ ->
×
63
        Result.(Ok ())
64
  in
65
  let blockchain_length =
×
66
    Envelope.Incoming.data enveloped_transition
×
67
    |> Mina_block.Validation.block |> Mina_block.blockchain_length
×
68
  in
69
  [%log internal] "@block_metadata"
×
70
    ~metadata:
71
      [ ("blockchain_length", Mina_numbers.Length.to_yojson blockchain_length) ] ;
×
72
  [%log internal] "Check_transition_not_in_frontier" ;
×
73
  let%bind () =
74
    Option.fold
×
75
      (Transition_frontier.find frontier transition_hash)
×
76
      ~init:Result.(Ok ())
77
      ~f:(fun _ _ -> Result.Error (`In_frontier transition_hash))
×
78
  in
79
  [%log internal] "Check_transition_not_in_process" ;
×
80
  let%bind () =
81
    Option.fold
×
82
      (Unprocessed_transition_cache.final_state unprocessed_transition_cache
×
83
         enveloped_transition )
84
      ~init:Result.(Ok ())
85
      ~f:(fun _ final_state -> Result.Error (`In_process final_state))
×
86
  in
87
  [%log internal] "Check_transition_can_be_connected" ;
×
88
  let module Context = struct
×
89
    include Context
90

91
    let logger =
92
      Logger.extend logger
×
93
        [ ("selection_context", `String "Transition_handler.Validator") ]
94
  end in
95
  let%map () =
96
    Result.ok_if_true
×
97
      (Consensus.Hooks.equal_select_status `Take
×
98
         (Consensus.Hooks.select
99
            ~context:(module Context)
100
            ~existing:
101
              (Transition_frontier.Breadcrumb.consensus_state_with_hashes
×
102
                 root_breadcrumb )
103
            ~candidate:(With_hash.map ~f:Mina_block.consensus_state transition) ) )
×
104
      ~error:`Disconnected
105
  in
106
  [%log internal] "Register_transition_for_processing" ;
×
107
  (* we expect this to be Ok since we just checked the cache *)
108
  Unprocessed_transition_cache.register_exn unprocessed_transition_cache
×
109
    enveloped_transition
110

111
let run ~context:(module Context : CONTEXT) ~trust_system ~time_controller
112
    ~frontier ~transition_reader
113
    ~(valid_transition_writer :
114
       ( [ `Block of
115
           ( Mina_block.initial_valid_block Envelope.Incoming.t
116
           , State_hash.t )
117
           Cached.t ]
118
         * [ `Valid_cb of Mina_net2.Validation_callback.t option ]
119
       , drop_head buffered
120
       , unit )
121
       Writer.t ) ~unprocessed_transition_cache =
122
  let open Context in
×
123
  let module Lru = Core_extended_cache.Lru in
124
  let outdated_root_cache = Lru.create ~destruct:None 1000 in
125
  O1trace.background_thread "validate_blocks_against_frontier" (fun () ->
×
126
      Reader.iter transition_reader
×
127
        ~f:(fun (`Block transition_env, `Valid_cb vc) ->
128
          let transition_with_hash, _ = Envelope.Incoming.data transition_env in
×
129
          let transition_hash =
×
130
            State_hash.With_state_hashes.state_hash transition_with_hash
131
          in
132
          Internal_tracing.Context_call.with_call_id
×
133
            ~tag:"transition_handler_validator"
134
          @@ fun () ->
135
          Internal_tracing.with_state_hash transition_hash
×
136
          @@ fun () ->
137
          let transition = With_hash.data transition_with_hash in
×
138
          let sender = Envelope.Incoming.sender transition_env in
×
139
          let slot_tx_end =
×
140
            Runtime_config.slot_tx_end
141
              precomputed_values.Precomputed_values.runtime_config
142
          in
143
          let slot_chain_end =
×
144
            Runtime_config.slot_chain_end precomputed_values.runtime_config
145
          in
146
          match
×
147
            validate_transition_is_relevant
148
              ~context:(module Context)
149
              ~frontier ~unprocessed_transition_cache ~slot_tx_end
150
              ~slot_chain_end transition_env
151
          with
152
          | Ok cached_transition ->
×
153
              let%map () =
154
                Trust_system.record_envelope_sender trust_system logger sender
×
155
                  ( Trust_system.Actions.Sent_useful_gossip
156
                  , Some
157
                      ( "external transition $state_hash"
158
                      , [ ("state_hash", State_hash.to_yojson transition_hash)
×
159
                        ; ("transition", Mina_block.to_yojson transition)
×
160
                        ] ) )
161
              in
162
              let transition_time =
×
163
                Mina_block.header transition
×
164
                |> Mina_block.Header.protocol_state
×
165
                |> Protocol_state.blockchain_state |> Blockchain_state.timestamp
×
166
                |> Block_time.to_time_exn
167
              in
168
              Perf_histograms.add_span
×
169
                ~name:"accepted_transition_remote_latency"
170
                (Core_kernel.Time.diff
×
171
                   Block_time.(now time_controller |> to_time_exn)
×
172
                   transition_time ) ;
173
              [%log internal] "Validate_transition_done" ;
×
174
              Writer.write valid_transition_writer
×
175
                (`Block cached_transition, `Valid_cb vc)
176
          | Error (`In_frontier _) | Error (`In_process _) ->
×
177
              [%log internal] "Failure"
×
178
                ~metadata:[ ("reason", `String "In_frontier or In_process") ] ;
179
              Trust_system.record_envelope_sender trust_system logger sender
×
180
                ( Trust_system.Actions.Sent_old_gossip
181
                , Some
182
                    ( "external transition with state hash $state_hash"
183
                    , [ ("state_hash", State_hash.to_yojson transition_hash)
×
184
                      ; ("transition", Mina_block.to_yojson transition)
×
185
                      ] ) )
186
          | Error `Disconnected ->
×
187
              [%log internal] "Failure"
×
188
                ~metadata:[ ("reason", `String "Disconnected") ] ;
189
              Mina_metrics.(Counter.inc_one Rejected_blocks.worse_than_root) ;
×
190
              let protocol_state =
191
                Mina_block.Header.protocol_state (Mina_block.header transition)
×
192
              in
193
              [%log error]
×
194
                ~metadata:
195
                  [ ("state_hash", State_hash.to_yojson transition_hash)
×
196
                  ; ("reason", `String "not selected over current root")
197
                  ; ( "protocol_state"
198
                    , Protocol_state.value_to_yojson protocol_state )
×
199
                  ]
200
                "Validation error: external transition with state hash \
201
                 $state_hash was rejected for reason $reason" ;
202
              let is_in_root_history =
×
203
                let open Transition_frontier.Extensions in
204
                get_extension
×
205
                  (Transition_frontier.extensions frontier)
×
206
                  Root_history
207
                |> Root_history.mem
×
208
              in
209
              let parent_hash =
210
                Protocol_state.previous_state_hash protocol_state
211
              in
212
              let action =
×
213
                if
214
                  is_in_root_history transition_hash
×
215
                  || Option.is_some
×
216
                       (Lru.find outdated_root_cache transition_hash)
×
217
                then Trust_system.Actions.Sent_old_gossip
×
218
                else if
×
219
                  is_in_root_history parent_hash
×
220
                  || Option.is_some (Lru.find outdated_root_cache parent_hash)
×
221
                then (
×
222
                  Lru.add outdated_root_cache ~key:transition_hash ~data:() ;
223
                  Sent_useless_gossip )
×
224
                else Disconnected_chain
×
225
              in
226
              Trust_system.record_envelope_sender trust_system logger sender
227
                ( action
228
                , Some
229
                    ( "received transition that was not connected to our chain \
230
                       from $sender"
231
                    , [ ( "sender"
232
                        , Envelope.Sender.to_yojson
×
233
                            (Envelope.Incoming.sender transition_env) )
×
234
                      ; ("transition", Mina_block.to_yojson transition)
×
235
                      ] ) )
236
          | Error `Non_empty_staged_ledger_diff_after_stop_slot ->
×
237
              [%log error]
×
238
                ~metadata:
239
                  [ ("state_hash", State_hash.to_yojson transition_hash)
×
240
                  ; ( "reason"
241
                    , `String "not empty staged ledger diff after slot_tx_end"
242
                    )
243
                  ; ( "block_slot"
244
                    , Mina_numbers.Global_slot_since_hard_fork.to_yojson
×
245
                      @@ Consensus.Data.Consensus_state.curr_global_slot
×
246
                      @@ Protocol_state.consensus_state @@ Header.protocol_state
×
247
                      @@ Mina_block.header @@ transition )
×
248
                  ]
249
                "Validation error: external transition with state hash \
250
                 $state_hash was rejected for reason $reason" ;
251
              Deferred.unit
×
252
          | Error `Block_after_after_stop_slot ->
×
253
              [%log error]
×
254
                ~metadata:
255
                  [ ("state_hash", State_hash.to_yojson transition_hash)
×
256
                  ; ("reason", `String "block after slot_chain_end")
257
                  ; ( "block_slot"
258
                    , Mina_numbers.Global_slot_since_hard_fork.to_yojson
×
259
                      @@ Consensus.Data.Consensus_state.curr_global_slot
×
260
                      @@ Protocol_state.consensus_state @@ Header.protocol_state
×
261
                      @@ Mina_block.header @@ transition )
×
262
                  ]
263
                "Validation error: external transition with state hash \
264
                 $state_hash was rejected for reason $reason" ;
265
              Deferred.unit ) )
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc