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

MinaProtocol / mina / 3409

26 Feb 2025 01:10PM UTC coverage: 32.353% (-28.4%) from 60.756%
3409

push

buildkite

web-flow
Merge pull request #16687 from MinaProtocol/dw/merge-compatible-into-develop-20250225

Merge compatible into develop [20250224]

23144 of 71535 relevant lines covered (32.35%)

16324.05 hits per line

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

1.54
/src/lib/transition_handler/breadcrumb_builder.ml
1
open Mina_base
4✔
2
open Core
3
open Async
4
open Cache_lib
5
open Network_peer
6

7
let build_subtrees_of_breadcrumbs ~proof_cache_db ~logger ~precomputed_values
8
    ~verifier ~trust_system ~frontier ~initial_hash
9
    subtrees_of_enveloped_transitions =
10
  let missing_parent_msg =
×
11
    Printf.sprintf
12
      "Transition frontier already garbage-collected the parent of %s"
13
      (Mina_base.State_hash.to_base58_check initial_hash)
×
14
  in
15
  (* If the breadcrumb we are targeting is removed from the transition
16
   * frontier while we're catching up, it means this path is not on the
17
   * critical path that has been chosen in the frontier. As such, we should
18
   * drop it on the floor. *)
19
  let breadcrumb_if_present logger =
×
20
    match Transition_frontier.find frontier initial_hash with
×
21
    | None ->
×
22
        [%log error]
×
23
          ~metadata:
24
            [ ("state_hash", Mina_base.State_hash.to_yojson initial_hash)
×
25
            ; ( "transition_hashes"
26
              , `List
27
                  (List.map subtrees_of_enveloped_transitions ~f:(fun subtree ->
×
28
                       Rose_tree.to_yojson
×
29
                         (fun (enveloped_transitions, _vc) ->
30
                           let transition, _ =
×
31
                             enveloped_transitions |> Cached.peek
×
32
                             |> Envelope.Incoming.data
33
                           in
34
                           Mina_base.State_hash.(
×
35
                             to_yojson (With_state_hashes.state_hash transition))
×
36
                           )
37
                         subtree ) ) )
38
            ]
39
          "Transition frontier already garbage-collected the parent of \
40
           $state_hash" ;
41
        Or_error.error_string missing_parent_msg
×
42
    | Some breadcrumb ->
×
43
        Or_error.return breadcrumb
44
  in
45
  Deferred.Or_error.List.map subtrees_of_enveloped_transitions
46
    ~f:(fun subtree_of_enveloped_transitions ->
47
      let%bind.Deferred.Or_error init_breadcrumb =
48
        breadcrumb_if_present
×
49
          (Logger.extend logger
×
50
             [ ("Check", `String "Before creating breadcrumb") ] )
51
        |> Deferred.return
×
52
      in
53
      Rose_tree.Deferred.Or_error.fold_map_over_subtrees
×
54
        subtree_of_enveloped_transitions
55
        ~init:(Cached.pure init_breadcrumb, None)
×
56
        ~f:(fun (cached_parent, _parent_vc)
57
                ( Rose_tree.T ((cached_enveloped_transition, valid_cb), _) as
58
                subtree ) ->
59
          let%map.Deferred cached_result =
60
            Cached.transform cached_enveloped_transition
×
61
              ~f:(fun enveloped_transition ->
62
                let open Deferred.Or_error.Let_syntax in
×
63
                let transition_with_initial_validation =
64
                  Envelope.Incoming.data enveloped_transition
65
                in
66
                let transition_receipt_time = Some (Time.now ()) in
×
67
                let transition_with_hash, _ =
68
                  transition_with_initial_validation
69
                in
70
                let mostly_validated_transition =
71
                  (* TODO: handle this edge case more gracefully *)
72
                  (* since we are building a disconnected subtree of breadcrumbs,
73
                   * we skip this step in validation *)
74
                  Mina_block.Validation.skip_frontier_dependencies_validation
75
                    `This_block_belongs_to_a_detached_subtree
76
                    transition_with_initial_validation
77
                in
78
                let sender = Envelope.Incoming.sender enveloped_transition in
×
79
                let parent = Cached.peek cached_parent in
×
80
                let expected_parent_hash =
×
81
                  Transition_frontier.Breadcrumb.state_hash parent
82
                in
83
                let actual_parent_hash =
×
84
                  transition_with_hash |> With_hash.data |> Mina_block.header
×
85
                  |> Mina_block.Header.protocol_state
×
86
                  |> Mina_state.Protocol_state.previous_state_hash
87
                in
88
                let%bind () =
89
                  Deferred.return
×
90
                    (Result.ok_if_true
×
91
                       (State_hash.equal actual_parent_hash expected_parent_hash)
×
92
                       ~error:
93
                         (Error.of_string
×
94
                            "Previous external transition hash does not equal \
95
                             to current external transition's parent hash" ) )
96
                in
97
                let open Deferred.Let_syntax in
×
98
                match%bind
99
                  Deferred.Or_error.try_with ~here:[%here] (fun () ->
×
100
                      Transition_frontier.Breadcrumb.build ~proof_cache_db
×
101
                        ~logger ~precomputed_values ~verifier ~trust_system
102
                        ~parent ~transition:mostly_validated_transition
103
                        ~get_completed_work:(Fn.const None)
×
104
                        ~sender:(Some sender) ~transition_receipt_time () )
105
                with
106
                | Error _ ->
×
107
                    Deferred.return @@ Or_error.error_string missing_parent_msg
×
108
                | Ok result -> (
×
109
                    match result with
110
                    | Ok new_breadcrumb ->
×
111
                        let open Result.Let_syntax in
112
                        Mina_metrics.(
113
                          Counter.inc_one
×
114
                            Transition_frontier_controller
115
                            .breadcrumbs_built_by_builder) ;
116
                        Deferred.return
117
                          (let%map (_ : Transition_frontier.Breadcrumb.t) =
118
                             breadcrumb_if_present
×
119
                               (Logger.extend logger
×
120
                                  [ ( "Check"
121
                                    , `String "After creating breadcrumb" )
122
                                  ] )
123
                           in
124
                           new_breadcrumb )
×
125
                    | Error err -> (
×
126
                        (* propagate bans through subtree *)
127
                        let subtree_nodes = Rose_tree.flatten subtree in
128
                        let ip_address_set =
×
129
                          let sender_from_tree_node node =
130
                            Envelope.Incoming.sender (Cached.peek node)
×
131
                          in
132
                          List.fold subtree_nodes
×
133
                            ~init:(Set.empty (module Network_peer.Peer))
×
134
                            ~f:(fun inet_addrs (node, _vc) ->
135
                              match sender_from_tree_node node with
×
136
                              | Local ->
×
137
                                  failwith
138
                                    "build_subtrees_of_breadcrumbs: sender of \
139
                                     external transition should not be Local"
140
                              | Remote peer ->
×
141
                                  Set.add inet_addrs peer )
142
                        in
143
                        let ip_addresses = Set.to_list ip_address_set in
144
                        let trust_system_record_invalid msg error =
×
145
                          let%map () =
146
                            Deferred.List.iter ip_addresses ~f:(fun ip_addr ->
×
147
                                Trust_system.record trust_system logger ip_addr
×
148
                                  ( Trust_system.Actions
149
                                    .Gossiped_invalid_transition
150
                                  , Some (msg, []) ) )
151
                          in
152
                          Error error
×
153
                        in
154
                        match err with
155
                        | `Invalid_staged_ledger_hash error ->
×
156
                            trust_system_record_invalid
157
                              "invalid staged ledger hash" error
158
                        | `Invalid_staged_ledger_diff error ->
×
159
                            trust_system_record_invalid
160
                              "invalid staged ledger diff" error
161
                        | `Fatal_error exn ->
×
162
                            Deferred.return (Or_error.of_exn exn) ) ) )
×
163
            |> Cached.sequence_deferred
×
164
          in
165
          Result.map ~f:(Fn.flip Tuple2.create valid_cb)
×
166
          @@ Cached.sequence_result cached_result ) )
×
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