Skip to main content

✅ Validate.v

Translated OCaml

Gitlab , OCaml

File generated by coq-of-ocaml
Since the expected features of preendorsement and endorsement are the same for all operations in the considered block, we compute them once and for all at the begining of the block.
See [expected_features_for_application], [expected_features_for_construction], and [expected_features_for_partial_construction] in the [Consensus] module below.
Module expected_features.
  Record record : Set := Build {
    level : Alpha_context.Raw_level.t;
    round : option Alpha_context.Round.t;
    branch : Block_hash.t;
    payload_hash : Block_payload_hash.t;
  }.
  Definition with_level level (r : record) :=
    Build level r.(round) r.(branch) r.(payload_hash).
  Definition with_round round (r : record) :=
    Build r.(level) round r.(branch) r.(payload_hash).
  Definition with_branch branch (r : record) :=
    Build r.(level) r.(round) branch r.(payload_hash).
  Definition with_payload_hash payload_hash (r : record) :=
    Build r.(level) r.(round) r.(branch) payload_hash.
End expected_features.
Definition expected_features := expected_features.record.

Records for the constructor parameters
Module ConstructorRecords_expected_preendorsement.
  Module expected_preendorsement.
    Module Expected_preendorsement.
      Record record {expected_features block_round : Set} : Set := Build {
        expected_features : expected_features;
        block_round : block_round;
      }.
      Arguments record : clear implicits.
      Definition with_expected_features {t_expected_features t_block_round}
        expected_features (r : record t_expected_features t_block_round) :=
        Build t_expected_features t_block_round expected_features
          r.(block_round).
      Definition with_block_round {t_expected_features t_block_round}
        block_round (r : record t_expected_features t_block_round) :=
        Build t_expected_features t_block_round r.(expected_features)
          block_round.
    End Expected_preendorsement.
    Definition Expected_preendorsement_skeleton :=
      Expected_preendorsement.record.

    Module No_expected_branch_for_partial_construction_preendorsement.
      Record record {expected_level : Set} : Set := Build {
        expected_level : expected_level;
      }.
      Arguments record : clear implicits.
      Definition with_expected_level {t_expected_level} expected_level
        (r : record t_expected_level) :=
        Build t_expected_level expected_level.
    End No_expected_branch_for_partial_construction_preendorsement.
    Definition
      No_expected_branch_for_partial_construction_preendorsement_skeleton :=
      No_expected_branch_for_partial_construction_preendorsement.record.
  End expected_preendorsement.
End ConstructorRecords_expected_preendorsement.
Import ConstructorRecords_expected_preendorsement.

Reserved Notation "'expected_preendorsement.Expected_preendorsement".
Reserved Notation
  "'expected_preendorsement.No_expected_branch_for_partial_construction_preendorsement".

Inductive expected_preendorsement : Set :=
| Expected_preendorsement :
  'expected_preendorsement.Expected_preendorsement expected_preendorsement
| No_locked_round_for_block_validation_preendorsement : expected_preendorsement
| Fresh_proposal_for_construction_preendorsement : expected_preendorsement
| No_expected_branch_for_partial_construction_preendorsement :
  'expected_preendorsement.No_expected_branch_for_partial_construction_preendorsement
   expected_preendorsement
| No_predecessor_info_cannot_validate_preendorsement : expected_preendorsement

where "'expected_preendorsement.Expected_preendorsement" :=
  (expected_preendorsement.Expected_preendorsement_skeleton expected_features
    (option Alpha_context.Round.t))
and "'expected_preendorsement.No_expected_branch_for_partial_construction_preendorsement"
  :=
  (expected_preendorsement.No_expected_branch_for_partial_construction_preendorsement_skeleton
    Alpha_context.Raw_level.t).

Module expected_preendorsement.
  Include ConstructorRecords_expected_preendorsement.expected_preendorsement.
  Definition Expected_preendorsement :=
    'expected_preendorsement.Expected_preendorsement.
  Definition No_expected_branch_for_partial_construction_preendorsement :=
    'expected_preendorsement.No_expected_branch_for_partial_construction_preendorsement.
End expected_preendorsement.

Records for the constructor parameters
Module ConstructorRecords_expected_endorsement.
  Module expected_endorsement.
    Module Expected_endorsement.
      Record record {expected_features : Set} : Set := Build {
        expected_features : expected_features;
      }.
      Arguments record : clear implicits.
      Definition with_expected_features {t_expected_features} expected_features
        (r : record t_expected_features) :=
        Build t_expected_features expected_features.
    End Expected_endorsement.
    Definition Expected_endorsement_skeleton := Expected_endorsement.record.

    Module No_expected_branch_for_partial_construction_endorsement.
      Record record {expected_level : Set} : Set := Build {
        expected_level : expected_level;
      }.
      Arguments record : clear implicits.
      Definition with_expected_level {t_expected_level} expected_level
        (r : record t_expected_level) :=
        Build t_expected_level expected_level.
    End No_expected_branch_for_partial_construction_endorsement.
    Definition No_expected_branch_for_partial_construction_endorsement_skeleton
      := No_expected_branch_for_partial_construction_endorsement.record.
  End expected_endorsement.
End ConstructorRecords_expected_endorsement.
Import ConstructorRecords_expected_endorsement.

Reserved Notation "'expected_endorsement.Expected_endorsement".
Reserved Notation
  "'expected_endorsement.No_expected_branch_for_partial_construction_endorsement".

Inductive expected_endorsement : Set :=
| Expected_endorsement :
  'expected_endorsement.Expected_endorsement expected_endorsement
| No_expected_branch_for_block_endorsement : expected_endorsement
| No_expected_branch_for_partial_construction_endorsement :
  'expected_endorsement.No_expected_branch_for_partial_construction_endorsement
   expected_endorsement
| No_predecessor_info_cannot_validate_endorsement : expected_endorsement

where "'expected_endorsement.Expected_endorsement" :=
  (expected_endorsement.Expected_endorsement_skeleton expected_features)
and "'expected_endorsement.No_expected_branch_for_partial_construction_endorsement"
  :=
  (expected_endorsement.No_expected_branch_for_partial_construction_endorsement_skeleton
    Alpha_context.Raw_level.t).

Module expected_endorsement.
  Include ConstructorRecords_expected_endorsement.expected_endorsement.
  Definition Expected_endorsement := 'expected_endorsement.Expected_endorsement.
  Definition No_expected_branch_for_partial_construction_endorsement :=
    'expected_endorsement.No_expected_branch_for_partial_construction_endorsement.
End expected_endorsement.

Module all_expected_consensus_features.
  Record record : Set := Build {
    expected_preendorsement : expected_preendorsement;
    expected_endorsement : expected_endorsement;
    expected_grandparent_endorsement_for_partial_construction :
      option expected_features;
  }.
  Definition with_expected_preendorsement expected_preendorsement
    (r : record) :=
    Build expected_preendorsement r.(expected_endorsement)
      r.(expected_grandparent_endorsement_for_partial_construction).
  Definition with_expected_endorsement expected_endorsement (r : record) :=
    Build r.(expected_preendorsement) expected_endorsement
      r.(expected_grandparent_endorsement_for_partial_construction).
  Definition with_expected_grandparent_endorsement_for_partial_construction
    expected_grandparent_endorsement_for_partial_construction (r : record) :=
    Build r.(expected_preendorsement) r.(expected_endorsement)
      expected_grandparent_endorsement_for_partial_construction.
End all_expected_consensus_features.
Definition all_expected_consensus_features :=
  all_expected_consensus_features.record.

Module consensus_info.
  Record record : Set := Build {
    all_expected_features : all_expected_consensus_features;
    preendorsement_slot_map :
      Alpha_context.Slot.Map.(Map.S.t) (Alpha_context.Consensus_key.pk × int);
    endorsement_slot_map :
      Alpha_context.Slot.Map.(Map.S.t) (Alpha_context.Consensus_key.pk × int);
  }.
  Definition with_all_expected_features all_expected_features (r : record) :=
    Build all_expected_features r.(preendorsement_slot_map)
      r.(endorsement_slot_map).
  Definition with_preendorsement_slot_map preendorsement_slot_map
    (r : record) :=
    Build r.(all_expected_features) preendorsement_slot_map
      r.(endorsement_slot_map).
  Definition with_endorsement_slot_map endorsement_slot_map (r : record) :=
    Build r.(all_expected_features) r.(preendorsement_slot_map)
      endorsement_slot_map.
End consensus_info.
Definition consensus_info := consensus_info.record.

Definition init_consensus_info
  (ctxt : Alpha_context.t)
  (all_expected_features : all_expected_consensus_features) : consensus_info :=
  {| consensus_info.all_expected_features := all_expected_features;
    consensus_info.preendorsement_slot_map :=
      Alpha_context.Consensus.allowed_preendorsements ctxt;
    consensus_info.endorsement_slot_map :=
      Alpha_context.Consensus.allowed_endorsements ctxt; |}.

Definition Consensus_content_map :=
  Map.Make
    (let t : Set := Alpha_context.consensus_content in
    let compare (function_parameter : Alpha_context.consensus_content)
      : Alpha_context.consensus_content int :=
      let '{|
        Alpha_context.consensus_content.slot := slot;
          Alpha_context.consensus_content.level := level;
          Alpha_context.consensus_content.round := round;
          Alpha_context.consensus_content.block_payload_hash :=
            block_payload_hash
          |} := function_parameter in
      fun (function_parameter : Alpha_context.consensus_content) ⇒
        let '{|
          Alpha_context.consensus_content.slot := slot';
            Alpha_context.consensus_content.level := level';
            Alpha_context.consensus_content.round := round';
            Alpha_context.consensus_content.block_payload_hash :=
              block_payload_hash'
            |} := function_parameter in
        Compare.or_else (Alpha_context.Raw_level.compare level level')
          (fun (function_parameter : unit) ⇒
            let '_ := function_parameter in
            Compare.or_else (Alpha_context.Slot.compare slot slot')
              (fun (function_parameter : unit) ⇒
                let '_ := function_parameter in
                Compare.or_else (Alpha_context.Round.compare round round')
                  (fun (function_parameter : unit) ⇒
                    let '_ := function_parameter in
                    Compare.or_else
                      (Block_payload_hash.compare block_payload_hash
                        block_payload_hash')
                      (fun (function_parameter : unit) ⇒
                        let '_ := function_parameter in
                        0)))) in
    {|
      Compare.COMPARABLE.compare := compare
    |}).

Module consensus_state.
  Record record : Set := Build {
    predecessor_level : Alpha_context.Raw_level.t;
    preendorsements_seen : Alpha_context.Slot.Map.(Map.S.t) Operation_hash.t;
    endorsements_seen : Alpha_context.Slot.Map.(Map.S.t) Operation_hash.t;
    grandparent_endorsements_seen :
      Alpha_context.Slot.Map.(Map.S.t) Operation_hash.t;
    dal_attestation_seen :
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.t)
        Operation_hash.t;
  }.
  Definition with_predecessor_level predecessor_level (r : record) :=
    Build predecessor_level r.(preendorsements_seen) r.(endorsements_seen)
      r.(grandparent_endorsements_seen) r.(dal_attestation_seen).
  Definition with_preendorsements_seen preendorsements_seen (r : record) :=
    Build r.(predecessor_level) preendorsements_seen r.(endorsements_seen)
      r.(grandparent_endorsements_seen) r.(dal_attestation_seen).
  Definition with_endorsements_seen endorsements_seen (r : record) :=
    Build r.(predecessor_level) r.(preendorsements_seen) endorsements_seen
      r.(grandparent_endorsements_seen) r.(dal_attestation_seen).
  Definition with_grandparent_endorsements_seen grandparent_endorsements_seen
    (r : record) :=
    Build r.(predecessor_level) r.(preendorsements_seen) r.(endorsements_seen)
      grandparent_endorsements_seen r.(dal_attestation_seen).
  Definition with_dal_attestation_seen dal_attestation_seen (r : record) :=
    Build r.(predecessor_level) r.(preendorsements_seen) r.(endorsements_seen)
      r.(grandparent_endorsements_seen) dal_attestation_seen.
End consensus_state.
Definition consensus_state := consensus_state.record.

Definition slot_map_encoding {A : Set}
  (element_encoding : Data_encoding.encoding A)
  : Data_encoding.encoding (Alpha_context.Slot.Map.(Map.S.t) A) :=
  Data_encoding.conv
    (fun (slot_map : Alpha_context.Slot.Map.(Map.S.t) A) ⇒
      Alpha_context.Slot.Map.(Map.S.bindings) slot_map)
    (fun (l_value : list (Alpha_context.Slot.t × A)) ⇒
      List.fold_left
        (fun (m_value : Alpha_context.Slot.Map.(Map.S.t) A) ⇒
          fun (function_parameter : Alpha_context.Slot.t × A) ⇒
            let '(k_value, v_value) := function_parameter in
            Alpha_context.Slot.Map.(Map.S.add) k_value v_value m_value)
        Alpha_context.Slot.Map.(Map.S.empty) l_value) None
    (Data_encoding.list_value None
      (Data_encoding.tup2 Alpha_context.Slot.encoding element_encoding)).

Definition consensus_state_encoding : Data_encoding.encoding consensus_state :=
  Data_encoding.def "consensus_state" None None
    (Data_encoding.conv
      (fun (function_parameter : consensus_state) ⇒
        let '{|
          consensus_state.predecessor_level := predecessor_level;
            consensus_state.preendorsements_seen := preendorsements_seen;
            consensus_state.endorsements_seen := endorsements_seen;
            consensus_state.grandparent_endorsements_seen :=
              grandparent_endorsements_seen;
            consensus_state.dal_attestation_seen := dal_attestation_seen
            |} := function_parameter in
        (predecessor_level, preendorsements_seen, endorsements_seen,
          grandparent_endorsements_seen, dal_attestation_seen))
      (fun (function_parameter :
        Alpha_context.Raw_level.t ×
          Alpha_context.Slot.Map.(Map.S.t) Operation_hash.t ×
          Alpha_context.Slot.Map.(Map.S.t) Operation_hash.t ×
          Alpha_context.Slot.Map.(Map.S.t) Operation_hash.t ×
          Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.t)
            Operation_hash.t) ⇒
        let
          '(predecessor_level, preendorsements_seen, endorsements_seen,
            grandparent_endorsements_seen, dal_attestation_seen) :=
          function_parameter in
        {| consensus_state.predecessor_level := predecessor_level;
          consensus_state.preendorsements_seen := preendorsements_seen;
          consensus_state.endorsements_seen := endorsements_seen;
          consensus_state.grandparent_endorsements_seen :=
            grandparent_endorsements_seen;
          consensus_state.dal_attestation_seen := dal_attestation_seen; |}) None
      (Data_encoding.obj5
        (Data_encoding.req None None "predecessor_level"
          Alpha_context.Raw_level.encoding)
        (Data_encoding.req None None "preendorsements_seen"
          (slot_map_encoding Operation_hash.encoding))
        (Data_encoding.req None None "endorsements_seen"
          (slot_map_encoding Operation_hash.encoding))
        (Data_encoding.req None None "grandparent_endorsements_seen"
          (slot_map_encoding Operation_hash.encoding))
        (Data_encoding.req None None "dal_attestation_seen"
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.encoding)
            Operation_hash.encoding)))).

Definition init_consensus_state (predecessor_level : Alpha_context.Raw_level.t)
  : consensus_state :=
  {| consensus_state.predecessor_level := predecessor_level;
    consensus_state.preendorsements_seen :=
      Alpha_context.Slot.Map.(Map.S.empty);
    consensus_state.endorsements_seen := Alpha_context.Slot.Map.(Map.S.empty);
    consensus_state.grandparent_endorsements_seen :=
      Alpha_context.Slot.Map.(Map.S.empty);
    consensus_state.dal_attestation_seen :=
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.empty);
    |}.

Module voting_state.
  Record record : Set := Build {
    proposals_seen :
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.t)
        Operation_hash.t;
    ballots_seen :
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.t)
        Operation_hash.t;
  }.
  Definition with_proposals_seen proposals_seen (r : record) :=
    Build proposals_seen r.(ballots_seen).
  Definition with_ballots_seen ballots_seen (r : record) :=
    Build r.(proposals_seen) ballots_seen.
End voting_state.
Definition voting_state := voting_state.record.

Definition voting_state_encoding : Data_encoding.encoding voting_state :=
  Data_encoding.def "voting_state" None None
    (Data_encoding.conv
      (fun (function_parameter : voting_state) ⇒
        let '{|
          voting_state.proposals_seen := proposals_seen;
            voting_state.ballots_seen := ballots_seen
            |} := function_parameter in
        (proposals_seen, ballots_seen))
      (fun (function_parameter :
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.t)
          Operation_hash.t ×
          Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.t)
            Operation_hash.t) ⇒
        let '(proposals_seen, ballots_seen) := function_parameter in
        {| voting_state.proposals_seen := proposals_seen;
          voting_state.ballots_seen := ballots_seen; |}) None
      (Data_encoding.obj2
        (Data_encoding.req None None "proposals_seen"
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.encoding)
            Operation_hash.encoding))
        (Data_encoding.req None None "ballots_seen"
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.encoding)
            Operation_hash.encoding)))).

Module Double_baking_evidence_map.
  Definition Map_Make_include :=
    Map.Make
      (let t : Set := Alpha_context.Raw_level.t × Alpha_context.Round.t in
      let compare
        (function_parameter : Alpha_context.Raw_level.t × Alpha_context.Round.t)
        : Alpha_context.Raw_level.t × Alpha_context.Round.t int :=
        let '(l_value, r_value) := function_parameter in
        fun (function_parameter :
          Alpha_context.Raw_level.t × Alpha_context.Round.t) ⇒
          let '(l', r') := function_parameter in
          Compare.or_else (Alpha_context.Raw_level.compare l_value l')
            (fun (function_parameter : unit) ⇒
              let '_ := function_parameter in
              Compare.or_else (Alpha_context.Round.compare r_value r')
                (fun (function_parameter : unit) ⇒
                  let '_ := function_parameter in
                  0)) in
      {|
        Compare.COMPARABLE.compare := compare
      |}).

Inclusion of the module [Map_Make_include]
  Definition key := Map_Make_include.(Map.S.key).

  Definition t := Map_Make_include.(Map.S.t).

  Definition empty {a : Set} := Map_Make_include.(Map.S.empty) (a := a).

  Definition is_empty {a : Set} := Map_Make_include.(Map.S.is_empty) (a := a).

  Definition mem {a : Set} := Map_Make_include.(Map.S.mem) (a := a).

  Definition add {a : Set} := Map_Make_include.(Map.S.add) (a := a).

  Definition update {a : Set} := Map_Make_include.(Map.S.update) (a := a).

  Definition singleton {a : Set} := Map_Make_include.(Map.S.singleton) (a := a).

  Definition remove {a : Set} := Map_Make_include.(Map.S.remove) (a := a).

  Definition merge {a b c : Set} :=
    Map_Make_include.(Map.S.merge) (a := a) (b := b) (c := c).

  Definition union {a : Set} := Map_Make_include.(Map.S.union) (a := a).

  Definition compare {a : Set} := Map_Make_include.(Map.S.compare) (a := a).

  Definition equal {a : Set} := Map_Make_include.(Map.S.equal) (a := a).

  Definition iter {a : Set} := Map_Make_include.(Map.S.iter) (a := a).

  Definition iter_e {a trace : Set} :=
    Map_Make_include.(Map.S.iter_e) (a := a) (trace := trace).

  Definition iter_s {a : Set} := Map_Make_include.(Map.S.iter_s) (a := a).

  Definition iter_p {a : Set} := Map_Make_include.(Map.S.iter_p) (a := a).

  Definition iter_es {a trace : Set} :=
    Map_Make_include.(Map.S.iter_es) (a := a) (trace := trace).

  Definition fold {a b : Set} :=
    Map_Make_include.(Map.S.fold) (a := a) (b := b).

  Definition fold_e {a b trace : Set} :=
    Map_Make_include.(Map.S.fold_e) (a := a) (b := b) (trace := trace).

  Definition fold_s {a b : Set} :=
    Map_Make_include.(Map.S.fold_s) (a := a) (b := b).

  Definition fold_es {a b trace : Set} :=
    Map_Make_include.(Map.S.fold_es) (a := a) (b := b) (trace := trace).

  Definition for_all {a : Set} := Map_Make_include.(Map.S.for_all) (a := a).

  Definition _exists {a : Set} := Map_Make_include.(Map.S._exists) (a := a).

  Definition filter {a : Set} := Map_Make_include.(Map.S.filter) (a := a).

  Definition filter_map {a b : Set} :=
    Map_Make_include.(Map.S.filter_map) (a := a) (b := b).

  Definition partition {a : Set} := Map_Make_include.(Map.S.partition) (a := a).

  Definition cardinal {a : Set} := Map_Make_include.(Map.S.cardinal) (a := a).

  Definition bindings {a : Set} := Map_Make_include.(Map.S.bindings) (a := a).

  Definition min_binding {a : Set} :=
    Map_Make_include.(Map.S.min_binding) (a := a).

  Definition min_binding_opt {a : Set} :=
    Map_Make_include.(Map.S.min_binding_opt) (a := a).

  Definition max_binding {a : Set} :=
    Map_Make_include.(Map.S.max_binding) (a := a).

  Definition max_binding_opt {a : Set} :=
    Map_Make_include.(Map.S.max_binding_opt) (a := a).

  Definition choose {a : Set} := Map_Make_include.(Map.S.choose) (a := a).

  Definition choose_opt {a : Set} :=
    Map_Make_include.(Map.S.choose_opt) (a := a).

  Definition split {a : Set} := Map_Make_include.(Map.S.split) (a := a).

  Definition find {a : Set} := Map_Make_include.(Map.S.find) (a := a).

  Definition find_opt {a : Set} := Map_Make_include.(Map.S.find_opt) (a := a).

  Definition find_first {a : Set} :=
    Map_Make_include.(Map.S.find_first) (a := a).

  Definition find_first_opt {a : Set} :=
    Map_Make_include.(Map.S.find_first_opt) (a := a).

  Definition find_last {a : Set} := Map_Make_include.(Map.S.find_last) (a := a).

  Definition find_last_opt {a : Set} :=
    Map_Make_include.(Map.S.find_last_opt) (a := a).

  Definition map {a b : Set} := Map_Make_include.(Map.S.map) (a := a) (b := b).

  Definition mapi {a b : Set} :=
    Map_Make_include.(Map.S.mapi) (a := a) (b := b).

  Definition to_seq {a : Set} := Map_Make_include.(Map.S.to_seq) (a := a).

  Definition to_rev_seq {a : Set} :=
    Map_Make_include.(Map.S.to_rev_seq) (a := a).

  Definition to_seq_from {a : Set} :=
    Map_Make_include.(Map.S.to_seq_from) (a := a).

  Definition add_seq {a : Set} := Map_Make_include.(Map.S.add_seq) (a := a).

  Definition of_seq {a : Set} := Map_Make_include.(Map.S.of_seq) (a := a).

  Definition iter_ep {a _error : Set} :=
    Map_Make_include.(Map.S.iter_ep) (a := a) (_error := _error).

  Definition encoding {A : Set} (elt_encoding : Data_encoding.encoding A)
    : Data_encoding.encoding (t A) :=
    Data_encoding.conv (fun (map : t A) ⇒ bindings map)
      (fun (l_value : list (key × A)) ⇒
        List.fold_left
          (fun (m_value : t A) ⇒
            fun (function_parameter : key × A) ⇒
              let '(k_value, v_value) := function_parameter in
              add k_value v_value m_value) empty l_value) None
      (Data_encoding.list_value None
        (Data_encoding.tup2
          (Data_encoding.tup2 Alpha_context.Raw_level.encoding
            Alpha_context.Round.encoding) elt_encoding)).

  (* Double_baking_evidence_map *)
  Definition module :=
    {|
      S.INDEXES_MAP.empty _ := empty;
      S.INDEXES_MAP.is_empty _ := is_empty;
      S.INDEXES_MAP.mem _ := mem;
      S.INDEXES_MAP.add _ := add;
      S.INDEXES_MAP.update _ := update;
      S.INDEXES_MAP.singleton _ := singleton;
      S.INDEXES_MAP.remove _ := remove;
      S.INDEXES_MAP.merge _ _ _ := merge;
      S.INDEXES_MAP.union _ := union;
      S.INDEXES_MAP.compare _ := compare;
      S.INDEXES_MAP.equal _ := equal;
      S.INDEXES_MAP.iter _ := iter;
      S.INDEXES_MAP.iter_e _ _ := iter_e;
      S.INDEXES_MAP.iter_s _ := iter_s;
      S.INDEXES_MAP.iter_p _ := iter_p;
      S.INDEXES_MAP.iter_es _ _ := iter_es;
      S.INDEXES_MAP.fold _ _ := fold;
      S.INDEXES_MAP.fold_e _ _ _ := fold_e;
      S.INDEXES_MAP.fold_s _ _ := fold_s;
      S.INDEXES_MAP.fold_es _ _ _ := fold_es;
      S.INDEXES_MAP.for_all _ := for_all;
      S.INDEXES_MAP._exists _ := _exists;
      S.INDEXES_MAP.filter _ := filter;
      S.INDEXES_MAP.filter_map _ _ := filter_map;
      S.INDEXES_MAP.partition _ := partition;
      S.INDEXES_MAP.cardinal _ := cardinal;
      S.INDEXES_MAP.bindings _ := bindings;
      S.INDEXES_MAP.min_binding _ := min_binding;
      S.INDEXES_MAP.min_binding_opt _ := min_binding_opt;
      S.INDEXES_MAP.max_binding _ := max_binding;
      S.INDEXES_MAP.max_binding_opt _ := max_binding_opt;
      S.INDEXES_MAP.choose _ := choose;
      S.INDEXES_MAP.choose_opt _ := choose_opt;
      S.INDEXES_MAP.split _ := split;
      S.INDEXES_MAP.find _ := find;
      S.INDEXES_MAP.find_opt _ := find_opt;
      S.INDEXES_MAP.find_first _ := find_first;
      S.INDEXES_MAP.find_first_opt _ := find_first_opt;
      S.INDEXES_MAP.find_last _ := find_last;
      S.INDEXES_MAP.find_last_opt _ := find_last_opt;
      S.INDEXES_MAP.map _ _ := map;
      S.INDEXES_MAP.mapi _ _ := mapi;
      S.INDEXES_MAP.to_seq _ := to_seq;
      S.INDEXES_MAP.to_rev_seq _ := to_rev_seq;
      S.INDEXES_MAP.to_seq_from _ := to_seq_from;
      S.INDEXES_MAP.add_seq _ := add_seq;
      S.INDEXES_MAP.of_seq _ := of_seq;
      S.INDEXES_MAP.iter_ep _ _ := iter_ep;
      S.INDEXES_MAP.encoding _ := encoding
    |}.
End Double_baking_evidence_map.
Definition Double_baking_evidence_map := Double_baking_evidence_map.module.

Module Double_endorsing_evidence_map.
  Definition Map_Make_include :=
    Map.Make
      (let t : Set :=
        Alpha_context.Raw_level.t × Alpha_context.Round.t × Alpha_context.Slot.t
        in
      let compare
        (function_parameter :
          Alpha_context.Raw_level.t × Alpha_context.Round.t ×
            Alpha_context.Slot.t)
        : Alpha_context.Raw_level.t × Alpha_context.Round.t ×
          Alpha_context.Slot.t int :=
        let '(l_value, r_value, s_value) := function_parameter in
        fun (function_parameter :
          Alpha_context.Raw_level.t × Alpha_context.Round.t ×
            Alpha_context.Slot.t) ⇒
          let '(l', r', s') := function_parameter in
          Compare.or_else (Alpha_context.Raw_level.compare l_value l')
            (fun (function_parameter : unit) ⇒
              let '_ := function_parameter in
              Compare.or_else (Alpha_context.Round.compare r_value r')
                (fun (function_parameter : unit) ⇒
                  let '_ := function_parameter in
                  Compare.or_else (Alpha_context.Slot.compare s_value s')
                    (fun (function_parameter : unit) ⇒
                      let '_ := function_parameter in
                      0))) in
      {|
        Compare.COMPARABLE.compare := compare
      |}).

Inclusion of the module [Map_Make_include]
  Definition key := Map_Make_include.(Map.S.key).

  Definition t := Map_Make_include.(Map.S.t).

  Definition empty {a : Set} := Map_Make_include.(Map.S.empty) (a := a).

  Definition is_empty {a : Set} := Map_Make_include.(Map.S.is_empty) (a := a).

  Definition mem {a : Set} := Map_Make_include.(Map.S.mem) (a := a).

  Definition add {a : Set} := Map_Make_include.(Map.S.add) (a := a).

  Definition update {a : Set} := Map_Make_include.(Map.S.update) (a := a).

  Definition singleton {a : Set} := Map_Make_include.(Map.S.singleton) (a := a).

  Definition remove {a : Set} := Map_Make_include.(Map.S.remove) (a := a).

  Definition merge {a b c : Set} :=
    Map_Make_include.(Map.S.merge) (a := a) (b := b) (c := c).

  Definition union {a : Set} := Map_Make_include.(Map.S.union) (a := a).

  Definition compare {a : Set} := Map_Make_include.(Map.S.compare) (a := a).

  Definition equal {a : Set} := Map_Make_include.(Map.S.equal) (a := a).

  Definition iter {a : Set} := Map_Make_include.(Map.S.iter) (a := a).

  Definition iter_e {a trace : Set} :=
    Map_Make_include.(Map.S.iter_e) (a := a) (trace := trace).

  Definition iter_s {a : Set} := Map_Make_include.(Map.S.iter_s) (a := a).

  Definition iter_p {a : Set} := Map_Make_include.(Map.S.iter_p) (a := a).

  Definition iter_es {a trace : Set} :=
    Map_Make_include.(Map.S.iter_es) (a := a) (trace := trace).

  Definition fold {a b : Set} :=
    Map_Make_include.(Map.S.fold) (a := a) (b := b).

  Definition fold_e {a b trace : Set} :=
    Map_Make_include.(Map.S.fold_e) (a := a) (b := b) (trace := trace).

  Definition fold_s {a b : Set} :=
    Map_Make_include.(Map.S.fold_s) (a := a) (b := b).

  Definition fold_es {a b trace : Set} :=
    Map_Make_include.(Map.S.fold_es) (a := a) (b := b) (trace := trace).

  Definition for_all {a : Set} := Map_Make_include.(Map.S.for_all) (a := a).

  Definition _exists {a : Set} := Map_Make_include.(Map.S._exists) (a := a).

  Definition filter {a : Set} := Map_Make_include.(Map.S.filter) (a := a).

  Definition filter_map {a b : Set} :=
    Map_Make_include.(Map.S.filter_map) (a := a) (b := b).

  Definition partition {a : Set} := Map_Make_include.(Map.S.partition) (a := a).

  Definition cardinal {a : Set} := Map_Make_include.(Map.S.cardinal) (a := a).

  Definition bindings {a : Set} := Map_Make_include.(Map.S.bindings) (a := a).

  Definition min_binding {a : Set} :=
    Map_Make_include.(Map.S.min_binding) (a := a).

  Definition min_binding_opt {a : Set} :=
    Map_Make_include.(Map.S.min_binding_opt) (a := a).

  Definition max_binding {a : Set} :=
    Map_Make_include.(Map.S.max_binding) (a := a).

  Definition max_binding_opt {a : Set} :=
    Map_Make_include.(Map.S.max_binding_opt) (a := a).

  Definition choose {a : Set} := Map_Make_include.(Map.S.choose) (a := a).

  Definition choose_opt {a : Set} :=
    Map_Make_include.(Map.S.choose_opt) (a := a).

  Definition split {a : Set} := Map_Make_include.(Map.S.split) (a := a).

  Definition find {a : Set} := Map_Make_include.(Map.S.find) (a := a).

  Definition find_opt {a : Set} := Map_Make_include.(Map.S.find_opt) (a := a).

  Definition find_first {a : Set} :=
    Map_Make_include.(Map.S.find_first) (a := a).

  Definition find_first_opt {a : Set} :=
    Map_Make_include.(Map.S.find_first_opt) (a := a).

  Definition find_last {a : Set} := Map_Make_include.(Map.S.find_last) (a := a).

  Definition find_last_opt {a : Set} :=
    Map_Make_include.(Map.S.find_last_opt) (a := a).

  Definition map {a b : Set} := Map_Make_include.(Map.S.map) (a := a) (b := b).

  Definition mapi {a b : Set} :=
    Map_Make_include.(Map.S.mapi) (a := a) (b := b).

  Definition to_seq {a : Set} := Map_Make_include.(Map.S.to_seq) (a := a).

  Definition to_rev_seq {a : Set} :=
    Map_Make_include.(Map.S.to_rev_seq) (a := a).

  Definition to_seq_from {a : Set} :=
    Map_Make_include.(Map.S.to_seq_from) (a := a).

  Definition add_seq {a : Set} := Map_Make_include.(Map.S.add_seq) (a := a).

  Definition of_seq {a : Set} := Map_Make_include.(Map.S.of_seq) (a := a).

  Definition iter_ep {a _error : Set} :=
    Map_Make_include.(Map.S.iter_ep) (a := a) (_error := _error).

  Definition encoding {A : Set} (elt_encoding : Data_encoding.encoding A)
    : Data_encoding.encoding (t A) :=
    Data_encoding.conv (fun (map : t A) ⇒ bindings map)
      (fun (l_value : list (key × A)) ⇒
        List.fold_left
          (fun (m_value : t A) ⇒
            fun (function_parameter : key × A) ⇒
              let '(k_value, v_value) := function_parameter in
              add k_value v_value m_value) empty l_value) None
      (Data_encoding.list_value None
        (Data_encoding.tup2
          (Data_encoding.tup3 Alpha_context.Raw_level.encoding
            Alpha_context.Round.encoding Alpha_context.Slot.encoding)
          elt_encoding)).

  (* Double_endorsing_evidence_map *)
  Definition module :=
    {|
      S.INDEXES_MAP.empty _ := empty;
      S.INDEXES_MAP.is_empty _ := is_empty;
      S.INDEXES_MAP.mem _ := mem;
      S.INDEXES_MAP.add _ := add;
      S.INDEXES_MAP.update _ := update;
      S.INDEXES_MAP.singleton _ := singleton;
      S.INDEXES_MAP.remove _ := remove;
      S.INDEXES_MAP.merge _ _ _ := merge;
      S.INDEXES_MAP.union _ := union;
      S.INDEXES_MAP.compare _ := compare;
      S.INDEXES_MAP.equal _ := equal;
      S.INDEXES_MAP.iter _ := iter;
      S.INDEXES_MAP.iter_e _ _ := iter_e;
      S.INDEXES_MAP.iter_s _ := iter_s;
      S.INDEXES_MAP.iter_p _ := iter_p;
      S.INDEXES_MAP.iter_es _ _ := iter_es;
      S.INDEXES_MAP.fold _ _ := fold;
      S.INDEXES_MAP.fold_e _ _ _ := fold_e;
      S.INDEXES_MAP.fold_s _ _ := fold_s;
      S.INDEXES_MAP.fold_es _ _ _ := fold_es;
      S.INDEXES_MAP.for_all _ := for_all;
      S.INDEXES_MAP._exists _ := _exists;
      S.INDEXES_MAP.filter _ := filter;
      S.INDEXES_MAP.filter_map _ _ := filter_map;
      S.INDEXES_MAP.partition _ := partition;
      S.INDEXES_MAP.cardinal _ := cardinal;
      S.INDEXES_MAP.bindings _ := bindings;
      S.INDEXES_MAP.min_binding _ := min_binding;
      S.INDEXES_MAP.min_binding_opt _ := min_binding_opt;
      S.INDEXES_MAP.max_binding _ := max_binding;
      S.INDEXES_MAP.max_binding_opt _ := max_binding_opt;
      S.INDEXES_MAP.choose _ := choose;
      S.INDEXES_MAP.choose_opt _ := choose_opt;
      S.INDEXES_MAP.split _ := split;
      S.INDEXES_MAP.find _ := find;
      S.INDEXES_MAP.find_opt _ := find_opt;
      S.INDEXES_MAP.find_first _ := find_first;
      S.INDEXES_MAP.find_first_opt _ := find_first_opt;
      S.INDEXES_MAP.find_last _ := find_last;
      S.INDEXES_MAP.find_last_opt _ := find_last_opt;
      S.INDEXES_MAP.map _ _ := map;
      S.INDEXES_MAP.mapi _ _ := mapi;
      S.INDEXES_MAP.to_seq _ := to_seq;
      S.INDEXES_MAP.to_rev_seq _ := to_rev_seq;
      S.INDEXES_MAP.to_seq_from _ := to_seq_from;
      S.INDEXES_MAP.add_seq _ := add_seq;
      S.INDEXES_MAP.of_seq _ := of_seq;
      S.INDEXES_MAP.iter_ep _ _ := iter_ep;
      S.INDEXES_MAP.encoding _ := encoding
    |}.
End Double_endorsing_evidence_map.
Definition Double_endorsing_evidence_map :=
  Double_endorsing_evidence_map.module.

State used and modified when validating anonymous operations. These fields are used to enforce that we do not validate the same operation multiple times.
Note that as part of {!state}, these maps live in memory. They are not explicitly bounded here, however: - In block validation mode, they are bounded by the number of anonymous operations allowed in the block. - In mempool mode, bounding the number of operations in this map is the responsability of the prevalidator on the shell side.
Module anonymous_state.
  Record record : Set := Build {
    activation_pkhs_seen :
      Ed25519.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.t)
        Operation_hash.t;
    double_baking_evidences_seen :
      Double_baking_evidence_map.(S.INDEXES_MAP.t) Operation_hash.t;
    double_endorsing_evidences_seen :
      Double_endorsing_evidence_map.(S.INDEXES_MAP.t) Operation_hash.t;
    seed_nonce_levels_seen :
      Alpha_context.Raw_level.Map.(Map.S.t) Operation_hash.t;
    vdf_solution_seen : option Operation_hash.t;
  }.
  Definition with_activation_pkhs_seen activation_pkhs_seen (r : record) :=
    Build activation_pkhs_seen r.(double_baking_evidences_seen)
      r.(double_endorsing_evidences_seen) r.(seed_nonce_levels_seen)
      r.(vdf_solution_seen).
  Definition with_double_baking_evidences_seen double_baking_evidences_seen
    (r : record) :=
    Build r.(activation_pkhs_seen) double_baking_evidences_seen
      r.(double_endorsing_evidences_seen) r.(seed_nonce_levels_seen)
      r.(vdf_solution_seen).
  Definition with_double_endorsing_evidences_seen
    double_endorsing_evidences_seen (r : record) :=
    Build r.(activation_pkhs_seen) r.(double_baking_evidences_seen)
      double_endorsing_evidences_seen r.(seed_nonce_levels_seen)
      r.(vdf_solution_seen).
  Definition with_seed_nonce_levels_seen seed_nonce_levels_seen (r : record) :=
    Build r.(activation_pkhs_seen) r.(double_baking_evidences_seen)
      r.(double_endorsing_evidences_seen) seed_nonce_levels_seen
      r.(vdf_solution_seen).
  Definition with_vdf_solution_seen vdf_solution_seen (r : record) :=
    Build r.(activation_pkhs_seen) r.(double_baking_evidences_seen)
      r.(double_endorsing_evidences_seen) r.(seed_nonce_levels_seen)
      vdf_solution_seen.
End anonymous_state.
Definition anonymous_state := anonymous_state.record.

Definition raw_level_map_encoding {A : Set}
  (elt_encoding : Data_encoding.encoding A)
  : Data_encoding.encoding (Alpha_context.Raw_level.Map.(Map.S.t) A) :=
  Data_encoding.conv
    (fun (map : Alpha_context.Raw_level.Map.(Map.S.t) A) ⇒
      Alpha_context.Raw_level.Map.(Map.S.bindings) map)
    (fun (l_value : list (Raw_level_repr.t × A)) ⇒
      List.fold_left
        (fun (m_value : Alpha_context.Raw_level.Map.(Map.S.t) A) ⇒
          fun (function_parameter : Raw_level_repr.t × A) ⇒
            let '(k_value, v_value) := function_parameter in
            Alpha_context.Raw_level.Map.(Map.S.add) k_value v_value m_value)
        Alpha_context.Raw_level.Map.(Map.S.empty) l_value) None
    (Data_encoding.list_value None
      (Data_encoding.tup2 Alpha_context.Raw_level.encoding elt_encoding)).

Definition anonymous_state_encoding : Data_encoding.encoding anonymous_state :=
  Data_encoding.def "anonymous_state" None None
    (Data_encoding.conv
      (fun (function_parameter : anonymous_state) ⇒
        let '{|
          anonymous_state.activation_pkhs_seen := activation_pkhs_seen;
            anonymous_state.double_baking_evidences_seen :=
              double_baking_evidences_seen;
            anonymous_state.double_endorsing_evidences_seen :=
              double_endorsing_evidences_seen;
            anonymous_state.seed_nonce_levels_seen := seed_nonce_levels_seen;
            anonymous_state.vdf_solution_seen := vdf_solution_seen
            |} := function_parameter in
        (activation_pkhs_seen, double_baking_evidences_seen,
          double_endorsing_evidences_seen, seed_nonce_levels_seen,
          vdf_solution_seen))
      (fun (function_parameter :
        Ed25519.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.t)
          Operation_hash.t ×
          Double_baking_evidence_map.(S.INDEXES_MAP.t) Operation_hash.t ×
          Double_endorsing_evidence_map.(S.INDEXES_MAP.t) Operation_hash.t ×
          Alpha_context.Raw_level.Map.(Map.S.t) Operation_hash.t ×
          option Operation_hash.t) ⇒
        let
          '(activation_pkhs_seen, double_baking_evidences_seen,
            double_endorsing_evidences_seen, seed_nonce_levels_seen,
            vdf_solution_seen) := function_parameter in
        {| anonymous_state.activation_pkhs_seen := activation_pkhs_seen;
          anonymous_state.double_baking_evidences_seen :=
            double_baking_evidences_seen;
          anonymous_state.double_endorsing_evidences_seen :=
            double_endorsing_evidences_seen;
          anonymous_state.seed_nonce_levels_seen := seed_nonce_levels_seen;
          anonymous_state.vdf_solution_seen := vdf_solution_seen; |}) None
      (Data_encoding.obj5
        (Data_encoding.req None None "activation_pkhs_seen"
          (Ed25519.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.encoding)
            Operation_hash.encoding))
        (Data_encoding.req None None "double_baking_evidences_seen"
          (Double_baking_evidence_map.(S.INDEXES_MAP.encoding)
            Operation_hash.encoding))
        (Data_encoding.req None None "double_endorsing_evidences_seen"
          (Double_endorsing_evidence_map.(S.INDEXES_MAP.encoding)
            Operation_hash.encoding))
        (Data_encoding.req None None "seed_nonce_levels_seen"
          (raw_level_map_encoding Operation_hash.encoding))
        (Data_encoding.opt None None "vdf_solution_seen" Operation_hash.encoding))).

Definition empty_anonymous_state : anonymous_state :=
  {|
    anonymous_state.activation_pkhs_seen :=
      Ed25519.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.empty);
    anonymous_state.double_baking_evidences_seen :=
      Double_baking_evidence_map.(S.INDEXES_MAP.empty);
    anonymous_state.double_endorsing_evidences_seen :=
      Double_endorsing_evidence_map.(S.INDEXES_MAP.empty);
    anonymous_state.seed_nonce_levels_seen :=
      Alpha_context.Raw_level.Map.(Map.S.empty);
    anonymous_state.vdf_solution_seen := None; |}.

Static information used to validate manager operations.
State used and modified when validating manager operations.
Module manager_state.
  Record record : Set := Build {
    managers_seen :
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.t)
        Operation_hash.t;
  }.
  Definition with_managers_seen managers_seen (r : record) :=
    Build managers_seen.
End manager_state.
Definition manager_state := manager_state.record.

Definition manager_state_encoding : Data_encoding.encoding manager_state :=
  Data_encoding.def "manager_state" None None
    (Data_encoding.conv
      (fun (function_parameter : manager_state) ⇒
        let '{| manager_state.managers_seen := managers_seen |} :=
          function_parameter in
        managers_seen)
      (fun (managers_seen :
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.t)
          Operation_hash.t) ⇒
        {| manager_state.managers_seen := managers_seen; |}) None
      (Data_encoding.obj1
        (Data_encoding.req None None "managers_seen"
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.encoding)
            Operation_hash.encoding)))).

Definition empty_manager_state : manager_state :=
  {|
    manager_state.managers_seen :=
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.empty);
    |}.

Mode-dependent information needed in final checks.
Circumstances in which operations are validated, and corresponding information. - [Application] is used for the validation of a preexisting block, often in preparation for its future application. - [Partial_validation] is used to quickly but partially validate a preexisting block, e.g. to quickly decide whether an alternate branch seems viable. In this mode, the initial {!type:context} may come from an ancestor block instead of the predecessor block. Only consensus operations are validated in this mode. - [Construction] is used for the construction of a new block. - [Mempool] is used by the {!module:Mempool} and by the [Partial_construction] mode in {!module:Main}, which may itself be used by RPCs or by another mempool implementation. (The [Mempool] mode is also used by the plugin.)
If you add a new mode, please make sure that it has a way to bound the size of the map {!recfield:manager_state.managers_seen}. Records for the constructor parameters
Module ConstructorRecords_mode.
  Module mode.
    Module Construction.
      Record record {predecessor_round predecessor_hash round
        block_data_contents block_producer payload_producer : Set} : Set := Build {
        predecessor_round : predecessor_round;
        predecessor_hash : predecessor_hash;
        round : round;
        block_data_contents : block_data_contents;
        block_producer : block_producer;
        payload_producer : payload_producer;
      }.
      Arguments record : clear implicits.
      Definition with_predecessor_round
        {t_predecessor_round t_predecessor_hash t_round t_block_data_contents
          t_block_producer t_payload_producer} predecessor_round
        (r :
          record t_predecessor_round t_predecessor_hash t_round
            t_block_data_contents t_block_producer t_payload_producer) :=
        Build t_predecessor_round t_predecessor_hash t_round
          t_block_data_contents t_block_producer t_payload_producer
          predecessor_round r.(predecessor_hash) r.(round)
          r.(block_data_contents) r.(block_producer) r.(payload_producer).
      Definition with_predecessor_hash
        {t_predecessor_round t_predecessor_hash t_round t_block_data_contents
          t_block_producer t_payload_producer} predecessor_hash
        (r :
          record t_predecessor_round t_predecessor_hash t_round
            t_block_data_contents t_block_producer t_payload_producer) :=
        Build t_predecessor_round t_predecessor_hash t_round
          t_block_data_contents t_block_producer t_payload_producer
          r.(predecessor_round) predecessor_hash r.(round)
          r.(block_data_contents) r.(block_producer) r.(payload_producer).
      Definition with_round
        {t_predecessor_round t_predecessor_hash t_round t_block_data_contents
          t_block_producer t_payload_producer} round
        (r :
          record t_predecessor_round t_predecessor_hash t_round
            t_block_data_contents t_block_producer t_payload_producer) :=
        Build t_predecessor_round t_predecessor_hash t_round
          t_block_data_contents t_block_producer t_payload_producer
          r.(predecessor_round) r.(predecessor_hash) round
          r.(block_data_contents) r.(block_producer) r.(payload_producer).
      Definition with_block_data_contents
        {t_predecessor_round t_predecessor_hash t_round t_block_data_contents
          t_block_producer t_payload_producer} block_data_contents
        (r :
          record t_predecessor_round t_predecessor_hash t_round
            t_block_data_contents t_block_producer t_payload_producer) :=
        Build t_predecessor_round t_predecessor_hash t_round
          t_block_data_contents t_block_producer t_payload_producer
          r.(predecessor_round) r.(predecessor_hash) r.(round)
          block_data_contents r.(block_producer) r.(payload_producer).
      Definition with_block_producer
        {t_predecessor_round t_predecessor_hash t_round t_block_data_contents
          t_block_producer t_payload_producer} block_producer
        (r :
          record t_predecessor_round t_predecessor_hash t_round
            t_block_data_contents t_block_producer t_payload_producer) :=
        Build t_predecessor_round t_predecessor_hash t_round
          t_block_data_contents t_block_producer t_payload_producer
          r.(predecessor_round) r.(predecessor_hash) r.(round)
          r.(block_data_contents) block_producer r.(payload_producer).
      Definition with_payload_producer
        {t_predecessor_round t_predecessor_hash t_round t_block_data_contents
          t_block_producer t_payload_producer} payload_producer
        (r :
          record t_predecessor_round t_predecessor_hash t_round
            t_block_data_contents t_block_producer t_payload_producer) :=
        Build t_predecessor_round t_predecessor_hash t_round
          t_block_data_contents t_block_producer t_payload_producer
          r.(predecessor_round) r.(predecessor_hash) r.(round)
          r.(block_data_contents) r.(block_producer) payload_producer.
    End Construction.
    Definition Construction_skeleton := Construction.record.
  End mode.
End ConstructorRecords_mode.
Import ConstructorRecords_mode.

Reserved Notation "'mode.Construction".

Inductive mode : Set :=
| Application : block_finalization_info mode
| Partial_validation : block_finalization_info mode
| Construction : 'mode.Construction mode
| Mempool : mode

where "'mode.Construction" :=
  (mode.Construction_skeleton Alpha_context.Round.t Block_hash.t
    Alpha_context.Round.t Alpha_context.Block_header.contents
    Alpha_context.Consensus_key.pk Alpha_context.Consensus_key.pk).

Module mode.
  Include ConstructorRecords_mode.mode.
  Definition Construction := 'mode.Construction.
End mode.

Module info.
  Record record : Set := Build {
    ctxt : Alpha_context.t;
    mode : mode;
    chain_id : Chain_id.t;
    current_level : Alpha_context.Level.t;
    consensus_info : consensus_info;
    manager_info : manager_info;
  }.
  Definition with_ctxt ctxt (r : record) :=
    Build ctxt r.(mode) r.(chain_id) r.(current_level) r.(consensus_info)
      r.(manager_info).
  Definition with_mode mode (r : record) :=
    Build r.(ctxt) mode r.(chain_id) r.(current_level) r.(consensus_info)
      r.(manager_info).
  Definition with_chain_id chain_id (r : record) :=
    Build r.(ctxt) r.(mode) chain_id r.(current_level) r.(consensus_info)
      r.(manager_info).
  Definition with_current_level current_level (r : record) :=
    Build r.(ctxt) r.(mode) r.(chain_id) current_level r.(consensus_info)
      r.(manager_info).
  Definition with_consensus_info consensus_info (r : record) :=
    Build r.(ctxt) r.(mode) r.(chain_id) r.(current_level) consensus_info
      r.(manager_info).
  Definition with_manager_info manager_info (r : record) :=
    Build r.(ctxt) r.(mode) r.(chain_id) r.(current_level) r.(consensus_info)
      manager_info.
End info.
Definition info := info.record.

Module operation_conflict_state.
  Record record : Set := Build {
    consensus_state : consensus_state;
    voting_state : voting_state;
    anonymous_state : anonymous_state;
    manager_state : manager_state;
  }.
  Definition with_consensus_state consensus_state (r : record) :=
    Build consensus_state r.(voting_state) r.(anonymous_state)
      r.(manager_state).
  Definition with_voting_state voting_state (r : record) :=
    Build r.(consensus_state) voting_state r.(anonymous_state)
      r.(manager_state).
  Definition with_anonymous_state anonymous_state (r : record) :=
    Build r.(consensus_state) r.(voting_state) anonymous_state
      r.(manager_state).
  Definition with_manager_state manager_state (r : record) :=
    Build r.(consensus_state) r.(voting_state) r.(anonymous_state)
      manager_state.
End operation_conflict_state.
Definition operation_conflict_state := operation_conflict_state.record.

Definition operation_conflict_state_encoding
  : Data_encoding.encoding operation_conflict_state :=
  Data_encoding.def "operation_conflict_state" None None
    (Data_encoding.conv
      (fun (function_parameter : operation_conflict_state) ⇒
        let '{|
          operation_conflict_state.consensus_state := consensus_state;
            operation_conflict_state.voting_state := voting_state;
            operation_conflict_state.anonymous_state := anonymous_state;
            operation_conflict_state.manager_state := manager_state
            |} := function_parameter in
        (consensus_state, voting_state, anonymous_state, manager_state))
      (fun (function_parameter :
        consensus_state × voting_state × anonymous_state × manager_state) ⇒
        let '(consensus_state, voting_state, anonymous_state, manager_state) :=
          function_parameter in
        {| operation_conflict_state.consensus_state := consensus_state;
          operation_conflict_state.voting_state := voting_state;
          operation_conflict_state.anonymous_state := anonymous_state;
          operation_conflict_state.manager_state := manager_state; |}) None
      (Data_encoding.obj4
        (Data_encoding.req None None "consensus_state" consensus_state_encoding)
        (Data_encoding.req None None "voting_state" voting_state_encoding)
        (Data_encoding.req None None "anonymous_state" anonymous_state_encoding)
        (Data_encoding.req None None "manager_state" manager_state_encoding))).

Module block_state.
  Record record : Set := Build {
    op_count : int;
    remaining_block_gas : Alpha_context.Gas.Arith.fp;
    recorded_operations_rev : list Operation_hash.t;
    last_op_validation_pass : option int;
    locked_round_evidence : option (Alpha_context.Round.t × int);
    endorsement_power : int;
  }.
  Definition with_op_count op_count (r : record) :=
    Build op_count r.(remaining_block_gas) r.(recorded_operations_rev)
      r.(last_op_validation_pass) r.(locked_round_evidence)
      r.(endorsement_power).
  Definition with_remaining_block_gas remaining_block_gas (r : record) :=
    Build r.(op_count) remaining_block_gas r.(recorded_operations_rev)
      r.(last_op_validation_pass) r.(locked_round_evidence)
      r.(endorsement_power).
  Definition with_recorded_operations_rev recorded_operations_rev
    (r : record) :=
    Build r.(op_count) r.(remaining_block_gas) recorded_operations_rev
      r.(last_op_validation_pass) r.(locked_round_evidence)
      r.(endorsement_power).
  Definition with_last_op_validation_pass last_op_validation_pass
    (r : record) :=
    Build r.(op_count) r.(remaining_block_gas) r.(recorded_operations_rev)
      last_op_validation_pass r.(locked_round_evidence) r.(endorsement_power).
  Definition with_locked_round_evidence locked_round_evidence (r : record) :=
    Build r.(op_count) r.(remaining_block_gas) r.(recorded_operations_rev)
      r.(last_op_validation_pass) locked_round_evidence r.(endorsement_power).
  Definition with_endorsement_power endorsement_power (r : record) :=
    Build r.(op_count) r.(remaining_block_gas) r.(recorded_operations_rev)
      r.(last_op_validation_pass) r.(locked_round_evidence) endorsement_power.
End block_state.
Definition block_state := block_state.record.

Module validation_state.
  Record record : Set := Build {
    info : info;
    operation_state : operation_conflict_state;
    block_state : block_state;
  }.
  Definition with_info info (r : record) :=
    Build info r.(operation_state) r.(block_state).
  Definition with_operation_state operation_state (r : record) :=
    Build r.(info) operation_state r.(block_state).
  Definition with_block_state block_state (r : record) :=
    Build r.(info) r.(operation_state) block_state.
End validation_state.
Definition validation_state := validation_state.record.

Definition ok_unit {A : Set} : Pervasives.result unit A :=
  Error_monad.Result_syntax.return_unit.

Definition init_info_aux
  (ctxt : Alpha_context.t) (mode : mode) (chain_id : Chain_id.t)
  (all_expected_consensus_characteristics : all_expected_consensus_features)
  : info :=
  {| info.ctxt := ctxt; info.mode := mode; info.chain_id := chain_id;
    info.current_level := Alpha_context.Level.current ctxt;
    info.consensus_info :=
      init_consensus_info ctxt all_expected_consensus_characteristics;
    info.manager_info := init_manager_info ctxt; |}.

Definition empty_voting_state : voting_state :=
  {|
    voting_state.proposals_seen :=
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.empty);
    voting_state.ballots_seen :=
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.empty);
    |}.

Definition init_operation_conflict_state
  (predecessor_level : Alpha_context.Raw_level.t) : operation_conflict_state :=
  {|
    operation_conflict_state.consensus_state :=
      init_consensus_state predecessor_level;
    operation_conflict_state.voting_state := empty_voting_state;
    operation_conflict_state.anonymous_state := empty_anonymous_state;
    operation_conflict_state.manager_state := empty_manager_state; |}.

Definition init_block_state (vi : info) : block_state :=
  {| block_state.op_count := 0;
    block_state.remaining_block_gas :=
      Alpha_context.Gas.Arith.fp_value
        (Alpha_context.Constants.hard_gas_limit_per_block vi.(info.ctxt));
    block_state.recorded_operations_rev := nil;
    block_state.last_op_validation_pass := None;
    block_state.locked_round_evidence := None;
    block_state.endorsement_power := 0; |}.

Definition get_initial_ctxt (function_parameter : validation_state)
  : Alpha_context.t :=
  let '{| validation_state.info := info_value |} := function_parameter in
  info_value.(info.ctxt).

Validation of consensus operations (validation pass [0]): preendorsement, endorsement, and dal_attestation.
Expected endorsement features for all modes in which a block is considered: application, partial validation, and construction.
  Definition expected_endorsement_for_block
    (ctxt : Alpha_context.t) (predecessor_level : Alpha_context.Level.t)
    (predecessor_round : Alpha_context.Round.t) : expected_endorsement :=
    match Alpha_context.Consensus.endorsement_branch ctxt with
    | NoneNo_expected_branch_for_block_endorsement
    | Some (branch, payload_hash)
      let expected_features :=
        expected_endorsement_features predecessor_level predecessor_round branch
          payload_hash in
      Expected_endorsement
        {|
          expected_endorsement.Expected_endorsement.expected_features :=
            expected_features; |}
    end.

Retrieve the expected consensus features for both application and partial validation modes.
  Definition expected_features_for_application
    (ctxt : Alpha_context.context) (fitness : Alpha_context.Fitness.t)
    (payload_hash : Block_payload_hash.t)
    (predecessor_level : Alpha_context.Level.t)
    (predecessor_round : Alpha_context.Round.t)
    (predecessor_hash : Block_hash.t) : all_expected_consensus_features :=
    let expected_preendorsement :=
      match Alpha_context.Fitness.locked_round fitness with
      | NoneNo_locked_round_for_block_validation_preendorsement
      | Some locked_round
        let expected_features :=
          {|
            expected_features.level :=
              (Alpha_context.Level.current ctxt).(Alpha_context.Level.t.level);
            expected_features.round := Some locked_round;
            expected_features.branch := predecessor_hash;
            expected_features.payload_hash := payload_hash; |} in
        let block_round := Some (Alpha_context.Fitness.round fitness) in
        Expected_preendorsement
          {|
            expected_preendorsement.Expected_preendorsement.expected_features :=
              expected_features;
            expected_preendorsement.Expected_preendorsement.block_round :=
              block_round; |}
      end in
    let expected_endorsement :=
      expected_endorsement_for_block ctxt predecessor_level predecessor_round in
    {|
      all_expected_consensus_features.expected_preendorsement :=
        expected_preendorsement;
      all_expected_consensus_features.expected_endorsement :=
        expected_endorsement;
      all_expected_consensus_features.expected_grandparent_endorsement_for_partial_construction
        := None; |}.

  Definition expected_features_for_construction
    (ctxt : Alpha_context.context) (round : Alpha_context.Round.t)
    (payload_hash : Block_payload_hash.t)
    (predecessor_level : Alpha_context.Level.t)
    (predecessor_round : Alpha_context.Round.t)
    (predecessor_hash : Block_hash.t) : all_expected_consensus_features :=
    let expected_preendorsement :=
      if Block_payload_hash.op_eq payload_hash Block_payload_hash.zero then
        Fresh_proposal_for_construction_preendorsement
      else
        let expected_features :=
          {|
            expected_features.level :=
              (Alpha_context.Level.current ctxt).(Alpha_context.Level.t.level);
            expected_features.round := None;
            expected_features.branch := predecessor_hash;
            expected_features.payload_hash := payload_hash; |} in
        Expected_preendorsement
          {|
            expected_preendorsement.Expected_preendorsement.expected_features :=
              expected_features;
            expected_preendorsement.Expected_preendorsement.block_round :=
              Some round; |} in
    let expected_endorsement :=
      expected_endorsement_for_block ctxt predecessor_level predecessor_round in
    {|
      all_expected_consensus_features.expected_preendorsement :=
        expected_preendorsement;
      all_expected_consensus_features.expected_endorsement :=
        expected_endorsement;
      all_expected_consensus_features.expected_grandparent_endorsement_for_partial_construction
        := None; |}.

  Definition expected_features_for_partial_construction
    (ctxt : Alpha_context.t) (predecessor_level : Alpha_context.Level.t)
    (predecessor_round : Alpha_context.Round.t)
    (grandparent_round : Alpha_context.Round.t)
    : all_expected_consensus_features :=
    let '(expected_preendorsement, expected_endorsement) :=
      match Alpha_context.Consensus.endorsement_branch ctxt with
      | None
        let expected_level := predecessor_level.(Alpha_context.Level.t.level) in
        ((No_expected_branch_for_partial_construction_preendorsement
          {|
            expected_preendorsement.No_expected_branch_for_partial_construction_preendorsement.expected_level
              := expected_level; |}),
          (No_expected_branch_for_partial_construction_endorsement
            {|
              expected_endorsement.No_expected_branch_for_partial_construction_endorsement.expected_level
                := expected_level; |}))
      | Some (branch, payload_hash)
        let expected_features :=
          expected_endorsement_features predecessor_level predecessor_round
            branch payload_hash in
        ((Expected_preendorsement
          {|
            expected_preendorsement.Expected_preendorsement.expected_features :=
              expected_features;
            expected_preendorsement.Expected_preendorsement.block_round := None;
            |}),
          (Expected_endorsement
            {|
              expected_endorsement.Expected_endorsement.expected_features :=
                expected_features; |}))
      end in
    let expected_grandparent_endorsement_for_partial_construction :=
      match
        ((Alpha_context.Consensus.grand_parent_branch ctxt),
          (Alpha_context.Raw_level.pred
            predecessor_level.(Alpha_context.Level.t.level))) with
      | ((None, _) | (_, None)) ⇒ None
      | (Some (branch, payload_hash), Some level)
        Some
          {| expected_features.level := level;
            expected_features.round := Some grandparent_round;
            expected_features.branch := branch;
            expected_features.payload_hash := payload_hash; |}
      end in
    {|
      all_expected_consensus_features.expected_preendorsement :=
        expected_preendorsement;
      all_expected_consensus_features.expected_endorsement :=
        expected_endorsement;
      all_expected_consensus_features.expected_grandparent_endorsement_for_partial_construction
        := expected_grandparent_endorsement_for_partial_construction; |}.

  Definition check_frozen_deposits_are_positive
    (ctxt : Alpha_context.context)
    (delegate_pkh : Alpha_context.public_key_hash) : M? unit :=
    let? frozen_deposits :=
      Alpha_context.Delegate.frozen_deposits ctxt delegate_pkh in
    Error_monad.fail_unless
      (Alpha_context.Tez.op_gt frozen_deposits.(Storage.deposits.current_amount)
        Alpha_context.Tez.zero)
      (Build_extensible "Zero_frozen_deposits" Alpha_context.public_key_hash
        delegate_pkh).

  Definition check_level_equal
    (kind_value : Validate_errors.Consensus.consensus_operation_kind)
    (expected_features : expected_features)
    (consensus_content : Alpha_context.consensus_content) : M? unit :=
    let expected := expected_features.(expected_features.level) in
    let provided := consensus_content.(Alpha_context.consensus_content.level) in
    Error_monad.error_unless (Alpha_context.Raw_level.equal expected provided)
      (if Alpha_context.Raw_level.op_gt expected provided then
        Build_extensible "Consensus_operation_for_old_level"
          Validate_errors.Consensus.Consensus_operation_for_old_level
          {|
            Validate_errors.Consensus.Consensus_operation_for_old_level.kind :=
              kind_value;
            Validate_errors.Consensus.Consensus_operation_for_old_level.expected
              := expected;
            Validate_errors.Consensus.Consensus_operation_for_old_level.provided
              := provided; |}
      else
        Build_extensible "Consensus_operation_for_future_level"
          Validate_errors.Consensus.Consensus_operation_for_future_level
          {|
            Validate_errors.Consensus.Consensus_operation_for_future_level.kind
              := kind_value;
            Validate_errors.Consensus.Consensus_operation_for_future_level.expected
              := expected;
            Validate_errors.Consensus.Consensus_operation_for_future_level.provided
              := provided; |}).

  Definition check_round
    (kind_value : Validate_errors.Consensus.consensus_operation_kind)
    (expected : Alpha_context.Round.t)
    (consensus_content : Alpha_context.consensus_content) : M? unit :=
    let provided := consensus_content.(Alpha_context.consensus_content.round) in
    Error_monad.error_unless (Alpha_context.Round.equal expected provided)
      (if Alpha_context.Round.op_gt expected provided then
        Build_extensible "Consensus_operation_for_old_round"
          Validate_errors.Consensus.Consensus_operation_for_old_round
          {|
            Validate_errors.Consensus.Consensus_operation_for_old_round.kind :=
              kind_value;
            Validate_errors.Consensus.Consensus_operation_for_old_round.expected
              := expected;
            Validate_errors.Consensus.Consensus_operation_for_old_round.provided
              := provided; |}
      else
        Build_extensible "Consensus_operation_for_future_round"
          Validate_errors.Consensus.Consensus_operation_for_future_round
          {|
            Validate_errors.Consensus.Consensus_operation_for_future_round.kind
              := kind_value;
            Validate_errors.Consensus.Consensus_operation_for_future_round.expected
              := expected;
            Validate_errors.Consensus.Consensus_operation_for_future_round.provided
              := provided; |}).

  Definition check_round_equal
    (kind_value : Validate_errors.Consensus.consensus_operation_kind)
    (expected_features : expected_features)
    (consensus_content : Alpha_context.consensus_content) : M? unit :=
    match expected_features.(expected_features.round) with
    | Some expectedcheck_round kind_value expected consensus_content
    | Noneok_unit
    end.

  Definition check_branch_equal
    (kind_value : Validate_errors.Consensus.consensus_operation_kind)
    (expected_features : expected_features)
    (operation : Alpha_context.operation) : M? unit :=
    let expected := expected_features.(expected_features.branch) in
    let provided :=
      operation.(Alpha_context.operation.shell).(Operation.shell_header.branch)
      in
    Error_monad.error_unless (Block_hash.equal expected provided)
      (Build_extensible "Wrong_consensus_operation_branch"
        Validate_errors.Consensus.Wrong_consensus_operation_branch
        {|
          Validate_errors.Consensus.Wrong_consensus_operation_branch.kind :=
            kind_value;
          Validate_errors.Consensus.Wrong_consensus_operation_branch.expected :=
            expected;
          Validate_errors.Consensus.Wrong_consensus_operation_branch.provided :=
            provided; |}).

  Definition check_payload_hash_equal
    (kind_value : Validate_errors.Consensus.consensus_operation_kind)
    (expected_features : expected_features)
    (consensus_content : Alpha_context.consensus_content) : M? unit :=
    let expected := expected_features.(expected_features.payload_hash) in
    let provided :=
      consensus_content.(Alpha_context.consensus_content.block_payload_hash) in
    Error_monad.error_unless (Block_payload_hash.equal expected provided)
      (Build_extensible "Wrong_payload_hash_for_consensus_operation"
        Validate_errors.Consensus.Wrong_payload_hash_for_consensus_operation
        {|
          Validate_errors.Consensus.Wrong_payload_hash_for_consensus_operation.kind
            := kind_value;
          Validate_errors.Consensus.Wrong_payload_hash_for_consensus_operation.expected
            := expected;
          Validate_errors.Consensus.Wrong_payload_hash_for_consensus_operation.provided
            := provided; |}).

  Definition check_consensus_features
    (kind_value : Validate_errors.Consensus.consensus_operation_kind)
    (expected : expected_features)
    (consensus_content : Alpha_context.consensus_content)
    (operation : Alpha_context.operation) : M? unit :=
    let? '_ := check_level_equal kind_value expected consensus_content in
    let? '_ := check_round_equal kind_value expected consensus_content in
    let? '_ := check_branch_equal kind_value expected operation in
    check_payload_hash_equal kind_value expected consensus_content.

  Definition get_expected_preendorsements_features
    (consensus_info : consensus_info)
    (consensus_content : Alpha_context.consensus_content)
    : M? (expected_features × option Alpha_context.Round.t) :=
    match
      consensus_info.(consensus_info.all_expected_features).(all_expected_consensus_features.expected_preendorsement)
      with
    |
      Expected_preendorsement {|
        expected_preendorsement.Expected_preendorsement.expected_features :=
          expected_features;
          expected_preendorsement.Expected_preendorsement.block_round :=
            block_round
          |} ⇒ return? (expected_features, block_round)
    |
      (No_locked_round_for_block_validation_preendorsement |
      Fresh_proposal_for_construction_preendorsement) ⇒
      Error_monad.error_value
        (Build_extensible "Unexpected_preendorsement_in_block" unit tt)
    |
      No_expected_branch_for_partial_construction_preendorsement {|
        expected_preendorsement.No_expected_branch_for_partial_construction_preendorsement.expected_level
          := expected_level
          |} ⇒
      Error_monad.error_value
        (Build_extensible "Consensus_operation_for_future_level"
          Validate_errors.Consensus.Consensus_operation_for_future_level
          {|
            Validate_errors.Consensus.Consensus_operation_for_future_level.kind
              := Validate_errors.Consensus.Preendorsement;
            Validate_errors.Consensus.Consensus_operation_for_future_level.expected
              := expected_level;
            Validate_errors.Consensus.Consensus_operation_for_future_level.provided
              := consensus_content.(Alpha_context.consensus_content.level); |})
    | No_predecessor_info_cannot_validate_preendorsement
      Error_monad.error_value
        (Build_extensible "Consensus_operation_not_allowed" unit tt)
    end.

  Definition check_round_not_too_high
    (block_round : option Alpha_context.Round.t)
    (provided : Alpha_context.Round.t) : M? unit :=
    match block_round with
    | Noneok_unit
    | Some block_round
      Error_monad.error_unless (Alpha_context.Round.op_lt provided block_round)
        (Build_extensible "Preendorsement_round_too_high"
          Validate_errors.Consensus.Preendorsement_round_too_high
          {|
            Validate_errors.Consensus.Preendorsement_round_too_high.block_round
              := block_round;
            Validate_errors.Consensus.Preendorsement_round_too_high.provided :=
              provided; |})
    end.

  Definition get_delegate_details {A : Set}
    (slot_map : Alpha_context.Slot.Map.(Map.S.t) A)
    (kind_value : Validate_errors.Consensus.consensus_operation_kind)
    (consensus_content : Alpha_context.consensus_content) : M? A :=
    Result.of_option
      (Error_monad.trace_of_error
        (Build_extensible "Wrong_slot_used_for_consensus_operation"
          Validate_errors.Consensus.Wrong_slot_used_for_consensus_operation
          {|
            Validate_errors.Consensus.Wrong_slot_used_for_consensus_operation.kind
              := kind_value; |}))
      (Alpha_context.Slot.Map.(Map.S.find)
        consensus_content.(Alpha_context.consensus_content.slot) slot_map).

  Definition check_preendorsement
    (vi : info) (check_signature : bool) (operation : Alpha_context.operation)
    : M? int :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Preendorsement consensus_content) ⇒
      let kind_value := Validate_errors.Consensus.Preendorsement in
      let? '(expected_features, block_round) :=
        get_expected_preendorsements_features vi.(info.consensus_info)
          consensus_content in
      let? '_ :=
        check_round_not_too_high block_round
          consensus_content.(Alpha_context.consensus_content.round) in
      let? '_ :=
        check_consensus_features kind_value expected_features consensus_content
          operation in
      let? '(consensus_key, voting_power) :=
        get_delegate_details
          vi.(info.consensus_info).(consensus_info.preendorsement_slot_map)
          kind_value consensus_content in
      let? '_ :=
        check_frozen_deposits_are_positive vi.(info.ctxt)
          consensus_key.(Raw_context.consensus_pk.delegate) in
      let? '_ :=
        if check_signature then
          Alpha_context.Operation.check_signature
            consensus_key.(Raw_context.consensus_pk.consensus_pk)
            vi.(info.chain_id) operation
        else
          ok_unit in
      return? voting_power
    | _unreachable_gadt_branch
    end.

  Definition check_preendorsement_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (op : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      op.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Preendorsement consensus_content) ⇒
      match
        Alpha_context.Slot.Map.(Map.S.find_opt)
          consensus_content.(Alpha_context.consensus_content.slot)
          vs.(operation_conflict_state.consensus_state).(consensus_state.preendorsements_seen)
        with
      | Some existing
        Pervasives.Error
          (Validate_errors.Operation_conflict
            {|
              Validate_errors.operation_conflict.Operation_conflict.existing :=
                existing;
              Validate_errors.operation_conflict.Operation_conflict.new_operation
                := oph; |})
      | Noneok_unit
      end
    | _unreachable_gadt_branch
    end.

  Definition wrap_preendorsement_conflict
    (function_parameter :
      Pervasives.result unit Validate_errors.operation_conflict) : M? unit :=
    match function_parameter with
    | Pervasives.Ok _ok_unit
    | Pervasives.Error conflict
      Error_monad.error_value
        (Build_extensible "Conflicting_consensus_operation"
          Validate_errors.Consensus.Conflicting_consensus_operation
          {|
            Validate_errors.Consensus.Conflicting_consensus_operation.kind :=
              Validate_errors.Consensus.Preendorsement;
            Validate_errors.Consensus.Conflicting_consensus_operation.conflict
              := conflict; |})
    end.

  Definition add_preendorsement
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (op : Alpha_context.operation) : operation_conflict_state :=
    match
      op.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Preendorsement consensus_content) ⇒
      let preendorsements_seen :=
        Alpha_context.Slot.Map.(Map.S.add)
          consensus_content.(Alpha_context.consensus_content.slot) oph
          vs.(operation_conflict_state.consensus_state).(consensus_state.preendorsements_seen)
        in
      operation_conflict_state.with_consensus_state
        (consensus_state.with_preendorsements_seen preendorsements_seen
          vs.(operation_conflict_state.consensus_state)) vs
    | _unreachable_gadt_branch
    end.

  Definition may_update_locked_round_evidence
    (block_state_value : block_state) (mode : mode)
    (consensus_content : Alpha_context.consensus_content) (voting_power : int)
    : block_state :=
    let locked_round_evidence :=
      match mode with
      | MempoolNone
      | (Application _ | Partial_validation _ | Construction _) ⇒
        match block_state_value.(block_state.locked_round_evidence) with
        | None
          Some
            (consensus_content.(Alpha_context.consensus_content.round),
              voting_power)
        | Some (_stored_round, evidences)
          Some
            (consensus_content.(Alpha_context.consensus_content.round),
              (evidences +i voting_power))
        end
      end in
    block_state.with_locked_round_evidence locked_round_evidence
      block_state_value.

  Definition remove_preendorsement
    (vs : operation_conflict_state) (operation : Alpha_context.operation)
    : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Preendorsement consensus_content) ⇒
      let preendorsements_seen :=
        Alpha_context.Slot.Map.(Map.S.remove)
          consensus_content.(Alpha_context.consensus_content.slot)
          vs.(operation_conflict_state.consensus_state).(consensus_state.preendorsements_seen)
        in
      operation_conflict_state.with_consensus_state
        (consensus_state.with_preendorsements_seen preendorsements_seen
          vs.(operation_conflict_state.consensus_state)) vs
    | _unreachable_gadt_branch
    end.

Validate an endorsement pointing to the grandparent block. This function will only be called in [Partial_construction] mode.
  Definition check_grandparent_endorsement
    (vi : info) (check_signature : bool) (expected : expected_features)
    (operation : Alpha_context.operation)
    (consensus_content : Alpha_context.consensus_content) : M? unit :=
    let kind_value := Validate_errors.Consensus.Grandparent_endorsement in
    let? level :=
      Alpha_context.Level.from_raw vi.(info.ctxt)
        consensus_content.(Alpha_context.consensus_content.level) in
    let? '(_ctxt, consensus_key) :=
      Alpha_context.Stake_distribution.slot_owner vi.(info.ctxt) level
        consensus_content.(Alpha_context.consensus_content.slot) in
    let? '_ :=
      check_consensus_features kind_value expected consensus_content operation
      in
    let? '_ :=
      if check_signature then
        Alpha_context.Operation.check_signature
          consensus_key.(Raw_context.consensus_pk.consensus_pk)
          vi.(info.chain_id) operation
      else
        ok_unit in
    Error_monad.Lwt_result_syntax.return_unit.

  Definition add_grandparent_endorsement
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (consensus_content : Alpha_context.consensus_content)
    : operation_conflict_state :=
    operation_conflict_state.with_consensus_state
      (consensus_state.with_grandparent_endorsements_seen
        (Alpha_context.Slot.Map.(Map.S.add)
          consensus_content.(Alpha_context.consensus_content.slot) oph
          vs.(operation_conflict_state.consensus_state).(consensus_state.grandparent_endorsements_seen))
        vs.(operation_conflict_state.consensus_state)) vs.

  Definition check_grandparent_endorsement_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (consensus_content : Alpha_context.consensus_content)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      Alpha_context.Slot.Map.(Map.S.find_opt)
        consensus_content.(Alpha_context.consensus_content.slot)
        vs.(operation_conflict_state.consensus_state).(consensus_state.grandparent_endorsements_seen)
      with
    | Noneok_unit
    | Some existing
      Pervasives.Error
        (Validate_errors.Operation_conflict
          {|
            Validate_errors.operation_conflict.Operation_conflict.existing :=
              existing;
            Validate_errors.operation_conflict.Operation_conflict.new_operation
              := oph; |})
    end.

  Definition remove_grandparent_endorsement
    (vs : operation_conflict_state)
    (consensus_content : Alpha_context.consensus_content)
    : operation_conflict_state :=
    let grandparent_endorsements_seen :=
      Alpha_context.Slot.Map.(Map.S.remove)
        consensus_content.(Alpha_context.consensus_content.slot)
        vs.(operation_conflict_state.consensus_state).(consensus_state.grandparent_endorsements_seen)
      in
    operation_conflict_state.with_consensus_state
      (consensus_state.with_grandparent_endorsements_seen
        grandparent_endorsements_seen
        vs.(operation_conflict_state.consensus_state)) vs.

  Definition get_expected_endorsements_features
    (consensus_info : consensus_info)
    (consensus_content : Alpha_context.consensus_content)
    : M? expected_features :=
    match
      consensus_info.(consensus_info.all_expected_features).(all_expected_consensus_features.expected_endorsement)
      with
    |
      Expected_endorsement {|
        expected_endorsement.Expected_endorsement.expected_features :=
          expected_features
          |} ⇒ return? expected_features
    | No_expected_branch_for_block_endorsement
      Error_monad.error_value
        (Build_extensible "Unexpected_endorsement_in_block" unit tt)
    |
      No_expected_branch_for_partial_construction_endorsement {|
        expected_endorsement.No_expected_branch_for_partial_construction_endorsement.expected_level
          := expected_level
          |} ⇒
      Error_monad.error_value
        (Build_extensible "Consensus_operation_for_future_level"
          Validate_errors.Consensus.Consensus_operation_for_future_level
          {|
            Validate_errors.Consensus.Consensus_operation_for_future_level.kind
              := Validate_errors.Consensus.Endorsement;
            Validate_errors.Consensus.Consensus_operation_for_future_level.expected
              := expected_level;
            Validate_errors.Consensus.Consensus_operation_for_future_level.provided
              := consensus_content.(Alpha_context.consensus_content.level); |})
    | No_predecessor_info_cannot_validate_endorsement
      Error_monad.error_value
        (Build_extensible "Consensus_operation_not_allowed" unit tt)
    end.

  Inductive endorsement_kind : Set :=
  | Grandparent_endorsement : endorsement_kind
  | Normal_endorsement : int endorsement_kind.

Validate an endorsement pointing to the predecessor, aka a "normal" endorsement. Only this kind of endorsement may be found during block validation or construction.
  Definition check_normal_endorsement
    (vi : info) (check_signature : bool) (operation : Alpha_context.operation)
    : M? int :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Endorsement consensus_content) ⇒
      let kind_value := Validate_errors.Consensus.Endorsement in
      let? expected_features :=
        get_expected_endorsements_features vi.(info.consensus_info)
          consensus_content in
      let? '_ :=
        check_consensus_features kind_value expected_features consensus_content
          operation in
      let? '(consensus_key, voting_power) :=
        get_delegate_details
          vi.(info.consensus_info).(consensus_info.endorsement_slot_map)
          kind_value consensus_content in
      let? '_ :=
        check_frozen_deposits_are_positive vi.(info.ctxt)
          consensus_key.(Raw_context.consensus_pk.delegate) in
      let? '_ :=
        if check_signature then
          Alpha_context.Operation.check_signature
            consensus_key.(Raw_context.consensus_pk.consensus_pk)
            vi.(info.chain_id) operation
        else
          ok_unit in
      return? voting_power
    | _unreachable_gadt_branch
    end.

  Definition check_normal_endorsement_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (consensus_content : Alpha_context.consensus_content)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      Alpha_context.Slot.Map.(Map.S.find_opt)
        consensus_content.(Alpha_context.consensus_content.slot)
        vs.(operation_conflict_state.consensus_state).(consensus_state.endorsements_seen)
      with
    | Noneok_unit
    | Some existing
      Pervasives.Error
        (Validate_errors.Operation_conflict
          {|
            Validate_errors.operation_conflict.Operation_conflict.existing :=
              existing;
            Validate_errors.operation_conflict.Operation_conflict.new_operation
              := oph; |})
    end.

  Definition add_normal_endorsement
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (consensus_content : Alpha_context.consensus_content)
    : operation_conflict_state :=
    operation_conflict_state.with_consensus_state
      (consensus_state.with_endorsements_seen
        (Alpha_context.Slot.Map.(Map.S.add)
          consensus_content.(Alpha_context.consensus_content.slot) oph
          vs.(operation_conflict_state.consensus_state).(consensus_state.endorsements_seen))
        vs.(operation_conflict_state.consensus_state)) vs.

  Definition remove_normal_endorsement
    (vs : operation_conflict_state)
    (consensus_content : Alpha_context.consensus_content)
    : operation_conflict_state :=
    let endorsements_seen :=
      Alpha_context.Slot.Map.(Map.S.remove)
        consensus_content.(Alpha_context.consensus_content.slot)
        vs.(operation_conflict_state.consensus_state).(consensus_state.endorsements_seen)
      in
    operation_conflict_state.with_consensus_state
      (consensus_state.with_endorsements_seen endorsements_seen
        vs.(operation_conflict_state.consensus_state)) vs.

  Definition check_endorsement
    (vi : info) (check_signature : bool) (operation : Alpha_context.operation)
    : M? endorsement_kind :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Endorsement consensus_content) ⇒
      match
        (vi.(info.consensus_info).(consensus_info.all_expected_features).(all_expected_consensus_features.expected_grandparent_endorsement_for_partial_construction),
          match
            vi.(info.consensus_info).(consensus_info.all_expected_features).(all_expected_consensus_features.expected_grandparent_endorsement_for_partial_construction)
            with
          | Some expected_grandparent_endorsement
            Alpha_context.Raw_level.op_eq
              consensus_content.(Alpha_context.consensus_content.level)
              expected_grandparent_endorsement.(expected_features.level)
          | _false
          end) with
      | (Some expected_grandparent_endorsement, true)
        let? '_ :=
          check_grandparent_endorsement vi check_signature
            expected_grandparent_endorsement operation consensus_content in
        return? Grandparent_endorsement
      | (_, _)
        let? voting_power :=
          check_normal_endorsement vi check_signature operation in
        return? (Normal_endorsement voting_power)
      end
    | _unreachable_gadt_branch
    end.

  Definition is_normal_endorsement_assuming_valid
    (vs : operation_conflict_state)
    (consensus_content : Alpha_context.consensus_content) : bool :=
    Alpha_context.Raw_level.equal
      vs.(operation_conflict_state.consensus_state).(consensus_state.predecessor_level)
      consensus_content.(Alpha_context.consensus_content.level).

  Definition check_endorsement_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Endorsement consensus_content) ⇒
      if is_normal_endorsement_assuming_valid vs consensus_content then
        check_normal_endorsement_conflict vs oph consensus_content
      else
        check_grandparent_endorsement_conflict vs oph consensus_content
    | _unreachable_gadt_branch
    end.

  Definition wrap_endorsement_conflict
    (function_parameter :
      Pervasives.result unit Validate_errors.operation_conflict) : M? unit :=
    match function_parameter with
    | Pervasives.Ok _ok_unit
    | Pervasives.Error conflict
      Error_monad.error_value
        (Build_extensible "Conflicting_consensus_operation"
          Validate_errors.Consensus.Conflicting_consensus_operation
          {|
            Validate_errors.Consensus.Conflicting_consensus_operation.kind :=
              Validate_errors.Consensus.Endorsement;
            Validate_errors.Consensus.Conflicting_consensus_operation.conflict
              := conflict; |})
    end.

  Definition add_endorsement
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (op : Alpha_context.operation) (endorsement_kind : endorsement_kind)
    : operation_conflict_state :=
    match
      op.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Endorsement consensus_content) ⇒
      match endorsement_kind with
      | Grandparent_endorsement
        add_grandparent_endorsement vs oph consensus_content
      | Normal_endorsement _voting_power
        add_normal_endorsement vs oph consensus_content
      end
    | _unreachable_gadt_branch
    end.

  Definition may_update_endorsement_power
    (block_state_value : block_state) (function_parameter : endorsement_kind)
    : block_state :=
    match function_parameter with
    | Grandparent_endorsementblock_state_value
    | Normal_endorsement voting_power
      block_state.with_endorsement_power
        (block_state_value.(block_state.endorsement_power) +i voting_power)
        block_state_value
    end.

  Definition remove_endorsement
    (vs : operation_conflict_state) (op : Alpha_context.operation)
    : operation_conflict_state :=
    match
      op.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Endorsement consensus_content) ⇒
      if is_normal_endorsement_assuming_valid vs consensus_content then
        remove_normal_endorsement vs consensus_content
      else
        remove_grandparent_endorsement vs consensus_content
    | _unreachable_gadt_branch
    end.

  Definition check_dal_attestation
    (vi : info) (operation : Alpha_context.operation) : M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Dal_attestation op) ⇒
      let? '_ := Dal_apply.validate_attestation vi.(info.ctxt) op in
      Error_monad.Lwt_result_syntax.return_unit
    | _unreachable_gadt_branch
    end.

  Definition check_dal_attestation_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Dal_attestation {|
          Alpha_context.Dal.Attestation.operation.attestor := attestor;
            Alpha_context.Dal.Attestation.operation.attestation := _;
            Alpha_context.Dal.Attestation.operation.level := _
            |}) ⇒
      match
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.find_opt)
          attestor
          vs.(operation_conflict_state.consensus_state).(consensus_state.dal_attestation_seen)
        with
      | Noneok_unit
      | Some existing
        Pervasives.Error
          (Validate_errors.Operation_conflict
            {|
              Validate_errors.operation_conflict.Operation_conflict.existing :=
                existing;
              Validate_errors.operation_conflict.Operation_conflict.new_operation
                := oph; |})
      end
    | _unreachable_gadt_branch
    end.

  Definition wrap_dal_attestation_conflict
    (function_parameter :
      Pervasives.result unit Validate_errors.operation_conflict) : M? unit :=
    match function_parameter with
    | Pervasives.Ok _ok_unit
    | Pervasives.Error conflict
      Error_monad.error_value
        (Build_extensible "Conflicting_consensus_operation"
          Validate_errors.Consensus.Conflicting_consensus_operation
          {|
            Validate_errors.Consensus.Conflicting_consensus_operation.kind :=
              Validate_errors.Consensus.Dal_attestation;
            Validate_errors.Consensus.Conflicting_consensus_operation.conflict
              := conflict; |})
    end.

  Definition add_dal_attestation
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Dal_attestation {|
          Alpha_context.Dal.Attestation.operation.attestor := attestor;
            Alpha_context.Dal.Attestation.operation.attestation := _;
            Alpha_context.Dal.Attestation.operation.level := _
            |}) ⇒
      operation_conflict_state.with_consensus_state
        (consensus_state.with_dal_attestation_seen
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.add)
            attestor oph
            vs.(operation_conflict_state.consensus_state).(consensus_state.dal_attestation_seen))
          vs.(operation_conflict_state.consensus_state)) vs
    | _unreachable_gadt_branch
    end.

  Definition remove_dal_attestation
    (vs : operation_conflict_state) (operation : Alpha_context.operation)
    : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Dal_attestation {|
          Alpha_context.Dal.Attestation.operation.attestor := attestor;
            Alpha_context.Dal.Attestation.operation.attestation := _;
            Alpha_context.Dal.Attestation.operation.level := _
            |}) ⇒
      let dal_attestation_seen :=
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.remove)
          attestor
          vs.(operation_conflict_state.consensus_state).(consensus_state.dal_attestation_seen)
        in
      operation_conflict_state.with_consensus_state
        (consensus_state.with_dal_attestation_seen dal_attestation_seen
          vs.(operation_conflict_state.consensus_state)) vs
    | _unreachable_gadt_branch
    end.

  Definition check_construction_preendorsement_round_consistency
    (vi : info) (block_state_value : block_state)
    (kind_value : Validate_errors.Consensus.consensus_operation_kind)
    (consensus_content : Alpha_context.consensus_content) : M? unit :=
    let? '(expected_features, _block_round) :=
      get_expected_preendorsements_features vi.(info.consensus_info)
        consensus_content in
    match expected_features.(expected_features.round) with
    | Some _Error_monad.Result_syntax.return_unit
    | None
      match block_state_value.(block_state.locked_round_evidence) with
      | NoneError_monad.Result_syntax.return_unit
      | Some (expected, _power)
        check_round kind_value expected consensus_content
      end
    end.

  Definition validate_preendorsement
    (check_signature : bool) (info_value : info)
    (operation_state : operation_conflict_state)
    (block_state_value : block_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : M? validation_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    | Alpha_context.Single (Alpha_context.Preendorsement consensus_content) ⇒
      let? voting_power :=
        check_preendorsement info_value check_signature operation in
      let? '_ :=
        check_construction_preendorsement_round_consistency info_value
          block_state_value Validate_errors.Consensus.Preendorsement
          consensus_content in
      let? '_ :=
        wrap_preendorsement_conflict
          (check_preendorsement_conflict operation_state oph operation) in
      let block_state_value :=
        may_update_locked_round_evidence block_state_value
          info_value.(info.mode) consensus_content voting_power in
      let operation_state := add_preendorsement operation_state oph operation in
      return?
        {| validation_state.info := info_value;
          validation_state.operation_state := operation_state;
          validation_state.block_state := block_state_value; |}
    | _unreachable_gadt_branch
    end.

  Definition validate_endorsement
    (check_signature : bool) (info_value : info)
    (operation_state : operation_conflict_state)
    (block_state_value : block_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : M? validation_state :=
    let? kind_value := check_endorsement info_value check_signature operation in
    let? '_ :=
      wrap_endorsement_conflict
        (check_endorsement_conflict operation_state oph operation) in
    let block_state_value :=
      may_update_endorsement_power block_state_value kind_value in
    let operation_state :=
      add_endorsement operation_state oph operation kind_value in
    return?
      {| validation_state.info := info_value;
        validation_state.operation_state := operation_state;
        validation_state.block_state := block_state_value; |}.
End Consensus.

Module Voting.
  Definition check_period_index (expected : int32) (period_index : int32)
    : M? unit :=
    Error_monad.error_unless (expected =i32 period_index)
      (Build_extensible "Wrong_voting_period_index"
        Validate_errors.Voting.Wrong_voting_period_index
        {|
          Validate_errors.Voting.Wrong_voting_period_index.expected := expected;
          Validate_errors.Voting.Wrong_voting_period_index.provided :=
            period_index; |}).

  Definition check_proposals_source_is_registered
    (ctxt : Alpha_context.context) (source : Alpha_context.public_key_hash)
    : M? unit :=
    let is_registered := Alpha_context.Delegate.registered ctxt source in
    Error_monad.fail_unless is_registered
      (Build_extensible "Proposals_from_unregistered_delegate"
        Alpha_context.public_key_hash source).

Check that the list of proposals is not empty and does not contain duplicates.
  Definition check_proposal_list_sanity (proposals : list Protocol_hash.t)
    : M? unit :=
    let? '_ :=
      match proposals with
      | []
        Error_monad.error_value (Build_extensible "Empty_proposals" unit tt)
      | cons _ _ok_unit
      end in
    let? '_ :=
      List.fold_left_e
        (fun (previous_elements : Protocol_hash._Set.(S.INDEXES_SET.t)) ⇒
          fun (proposal : Protocol_hash.t) ⇒
            let? '_ :=
              Error_monad.error_when
                (Protocol_hash._Set.(S.INDEXES_SET.mem) proposal
                  previous_elements)
                (Build_extensible "Proposals_contain_duplicate"
                  Validate_errors.Voting.Proposals_contain_duplicate
                  {|
                    Validate_errors.Voting.Proposals_contain_duplicate.proposal
                      := proposal; |}) in
            return?
              (Protocol_hash._Set.(S.INDEXES_SET.add) proposal previous_elements))
        Protocol_hash._Set.(S.INDEXES_SET.empty) proposals in
    Error_monad.Result_syntax.return_unit.

  Definition check_period_kind_for_proposals
    (current_period : Alpha_context.Voting_period.voting_period) : M? unit :=
    match current_period.(Alpha_context.Voting_period.voting_period.kind) with
    | Alpha_context.Voting_period.Proposalok_unit
    |
      (Alpha_context.Voting_period.Exploration |
      Alpha_context.Voting_period.Cooldown |
      Alpha_context.Voting_period.Promotion |
      Alpha_context.Voting_period.Adoption) as current
      Error_monad.error_value
        (Build_extensible "Wrong_voting_period_kind"
          Validate_errors.Voting.Wrong_voting_period_kind
          {| Validate_errors.Voting.Wrong_voting_period_kind.current := current;
            Validate_errors.Voting.Wrong_voting_period_kind.expected :=
              [ Alpha_context.Voting_period.Proposal ]; |})
    end.

  Definition check_in_listings
    (ctxt : Alpha_context.context) (source : Alpha_context.public_key_hash)
    : M? unit :=
    let in_listings := Alpha_context.Vote.in_listings ctxt source in
    Error_monad.fail_unless in_listings
      (Build_extensible "Source_not_in_vote_listings" unit tt).

  Definition check_count (count_in_ctxt : int) (proposals_length : int)
    : M? unit :=
    let? '_ :=
      Internal_errors.do_assert
        (count_in_ctxt i Alpha_context.Constants.max_proposals_per_delegate)
      in
    Error_monad.error_unless
      ((count_in_ctxt +i proposals_length) i
      Alpha_context.Constants.max_proposals_per_delegate)
      (Build_extensible "Too_many_proposals"
        Validate_errors.Voting.Too_many_proposals
        {|
          Validate_errors.Voting.Too_many_proposals.previous_count :=
            count_in_ctxt;
          Validate_errors.Voting.Too_many_proposals.operation_count :=
            proposals_length; |}).

  Definition check_already_proposed
    (ctxt : Alpha_context.context) (proposer : Alpha_context.public_key_hash)
    (proposals : list Alpha_context.Vote.proposal) : M? unit :=
    List.iter_es
      (fun (proposal : Alpha_context.Vote.proposal) ⇒
        let already_proposed :=
          Alpha_context.Vote.has_proposed ctxt proposer proposal in
        Error_monad.fail_when already_proposed
          (Build_extensible "Already_proposed"
            Validate_errors.Voting.Already_proposed
            {| Validate_errors.Voting.Already_proposed.proposal := proposal; |}))
      proposals.

Check that the [apply_testnet_dictator_proposals] function in {!module:Amendment} will not fail.
The current function is designed to be exclusively called by [check_proposals] right below.
@return [Error Testnet_dictator_multiple_proposals] if [proposals] has more than one element.
  Definition check_testnet_dictator_proposals {A : Set}
    (chain_id : Chain_id.t) (proposals : list A) : M? unit :=
    let '_ :=
      (* ❌ Assert instruction is not handled. *)
      assert unit (Chain_id.op_ltgt chain_id Alpha_context.Constants.mainnet_id)
      in
    match proposals with
    | ([] | cons _ []) ⇒ ok_unit
    | cons _ (cons _ _) ⇒
      Error_monad.error_value
        (Build_extensible "Testnet_dictator_multiple_proposals" unit tt)
    end.

Check that a Proposals operation can be safely applied.
@return [Error Wrong_voting_period_index] if the operation's period and the current period in the {!type:context} do not have the same index.
@return [Error Proposals_from_unregistered_delegate] if the source is not a registered delegate.
@return [Error Empty_proposals] if the list of proposals is empty.
@return [Error Proposals_contain_duplicate] if the list of proposals contains a duplicate element.
@return [Error Wrong_voting_period_kind] if the voting period is not of the Proposal kind.
@return [Error Source_not_in_vote_listings] if the source is not in the vote listings.
@return [Error Too_many_proposals] if the operation causes the source's total number of proposals during the current voting period to exceed {!Constants.max_proposals_per_delegate}.
@return [Error Already_proposed] if one of the proposals has already been proposed by the source in the current voting period.
@return [Error Testnet_dictator_multiple_proposals] if the source is a testnet dictator and the operation contains more than one proposal.
@return [Error Operation.Missing_signature] or [Error Operation.Invalid_signature] if the operation is unsigned or incorrectly signed.
  Definition check_proposals
    (vi : info) (check_signature : bool) (operation : Alpha_context.operation)
    : M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Proposals {|
          Alpha_context.contents.Proposals.source := source;
            Alpha_context.contents.Proposals.period := period;
            Alpha_context.contents.Proposals.proposals := proposals
            |}) ⇒
      let? current_period :=
        Alpha_context.Voting_period.get_current vi.(info.ctxt) in
      let? '_ :=
        check_period_index
          current_period.(Alpha_context.Voting_period.voting_period.index)
          period in
      let? '_ :=
        if
          Amendment.is_testnet_dictator vi.(info.ctxt) vi.(info.chain_id) source
        then
          let? '_ :=
            check_testnet_dictator_proposals vi.(info.chain_id) proposals in
          Error_monad.Lwt_result_syntax.return_unit
        else
          let? '_ := check_proposals_source_is_registered vi.(info.ctxt) source
            in
          let? '_ := check_proposal_list_sanity proposals in
          let? '_ := check_period_kind_for_proposals current_period in
          let? '_ := check_in_listings vi.(info.ctxt) source in
          let? count_in_ctxt :=
            Alpha_context.Vote.get_delegate_proposal_count vi.(info.ctxt) source
            in
          let proposals_length := List.length proposals in
          let? '_ := check_count count_in_ctxt proposals_length in
          check_already_proposed vi.(info.ctxt) source proposals in
      if check_signature then
        let? public_key :=
          Alpha_context.Contract.get_manager_key None vi.(info.ctxt) source in
        Alpha_context.Operation.check_signature public_key vi.(info.chain_id)
          operation
      else
        Error_monad.Lwt_result_syntax.return_unit
    | _unreachable_gadt_branch
    end.

Check that a Proposals operation is compatible with previously validated operations in the current block/mempool.
@return [Error Operation_conflict] if the current block/mempool already contains a Proposals operation from the same source (regardless of whether this source is a testnet dictator or an ordinary manager).
  Definition check_proposals_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Proposals {|
          Alpha_context.contents.Proposals.source := source |}) ⇒
      match
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.find_opt)
          source
          vs.(operation_conflict_state.voting_state).(voting_state.proposals_seen)
        with
      | NoneError_monad.Result_syntax.return_unit
      | Some existing
        Pervasives.Error
          (Validate_errors.Operation_conflict
            {|
              Validate_errors.operation_conflict.Operation_conflict.existing :=
                existing;
              Validate_errors.operation_conflict.Operation_conflict.new_operation
                := oph; |})
      end
    | _unreachable_gadt_branch
    end.

  Definition wrap_proposals_conflict
    (function_parameter :
      Pervasives.result unit Validate_errors.operation_conflict) : M? unit :=
    match function_parameter with
    | Pervasives.Ok _ok_unit
    | Pervasives.Error conflict
      Error_monad.error_value
        (Build_extensible "Conflicting_proposals"
          Validate_errors.operation_conflict conflict)
    end.

  Definition add_proposals
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Proposals {|
          Alpha_context.contents.Proposals.source := source |}) ⇒
      let proposals_seen :=
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.add)
          source oph
          vs.(operation_conflict_state.voting_state).(voting_state.proposals_seen)
        in
      let voting_state :=
        voting_state.with_proposals_seen proposals_seen
          vs.(operation_conflict_state.voting_state) in
      operation_conflict_state.with_voting_state voting_state vs
    | _unreachable_gadt_branch
    end.

  Definition remove_proposals
    (vs : operation_conflict_state) (operation : Alpha_context.operation)
    : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Proposals {|
          Alpha_context.contents.Proposals.source := source |}) ⇒
      let proposals_seen :=
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.remove)
          source
          vs.(operation_conflict_state.voting_state).(voting_state.proposals_seen)
        in
      operation_conflict_state.with_voting_state
        (voting_state.with_proposals_seen proposals_seen
          vs.(operation_conflict_state.voting_state)) vs
    | _unreachable_gadt_branch
    end.

  Definition check_ballot_source_is_registered
    (ctxt : Alpha_context.context) (source : Alpha_context.public_key_hash)
    : M? unit :=
    let is_registered := Alpha_context.Delegate.registered ctxt source in
    Error_monad.fail_unless is_registered
      (Build_extensible "Ballot_from_unregistered_delegate"
        Alpha_context.public_key_hash source).

  Definition check_period_kind_for_ballot
    (current_period : Alpha_context.Voting_period.voting_period) : M? unit :=
    match current_period.(Alpha_context.Voting_period.voting_period.kind) with
    |
      (Alpha_context.Voting_period.Exploration |
      Alpha_context.Voting_period.Promotion) ⇒ ok_unit
    |
      (Alpha_context.Voting_period.Cooldown |
      Alpha_context.Voting_period.Proposal |
      Alpha_context.Voting_period.Adoption) as current
      Error_monad.error_value
        (Build_extensible "Wrong_voting_period_kind"
          Validate_errors.Voting.Wrong_voting_period_kind
          {| Validate_errors.Voting.Wrong_voting_period_kind.current := current;
            Validate_errors.Voting.Wrong_voting_period_kind.expected :=
              [
                Alpha_context.Voting_period.Exploration;
                Alpha_context.Voting_period.Promotion
              ]; |})
    end.

  Definition check_current_proposal
    (ctxt : Alpha_context.context) (op_proposal : Protocol_hash.t) : M? unit :=
    let? current_proposal := Alpha_context.Vote.get_current_proposal ctxt in
    Error_monad.fail_unless (Protocol_hash.equal op_proposal current_proposal)
      (Build_extensible "Ballot_for_wrong_proposal"
        Validate_errors.Voting.Ballot_for_wrong_proposal
        {|
          Validate_errors.Voting.Ballot_for_wrong_proposal.current :=
            current_proposal;
          Validate_errors.Voting.Ballot_for_wrong_proposal.submitted :=
            op_proposal; |}).

  Definition check_source_has_not_already_voted
    (ctxt : Alpha_context.context) (source : Alpha_context.public_key_hash)
    : M? unit :=
    let has_ballot := Alpha_context.Vote.has_recorded_ballot ctxt source in
    Error_monad.fail_when has_ballot
      (Build_extensible "Already_submitted_a_ballot" unit tt).

Check that a Ballot operation can be safely applied.
@return [Error Ballot_from_unregistered_delegate] if the source is not a registered delegate.
@return [Error Wrong_voting_period_index] if the operation's period and the current period in the {!type:context} do not have the same index.
@return [Error Wrong_voting_period_kind] if the voting period is not of the Exploration or Promotion kind.
@return [Error Ballot_for_wrong_proposal] if the operation's proposal is different from the current proposal in the context.
@return [Error Already_submitted_a_ballot] if the source has already voted during the current voting period.
@return [Error Source_not_in_vote_listings] if the source is not in the vote listings.
@return [Error Operation.Missing_signature] or [Error Operation.Invalid_signature] if the operation is unsigned or incorrectly signed.
  Definition check_ballot
    (vi : info) (check_signature : bool) (operation : Alpha_context.operation)
    : M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Ballot {|
          Alpha_context.contents.Ballot.source := source;
            Alpha_context.contents.Ballot.period := period;
            Alpha_context.contents.Ballot.proposal := proposal;
            Alpha_context.contents.Ballot.ballot := _
            |}) ⇒
      let? '_ := check_ballot_source_is_registered vi.(info.ctxt) source in
      let? current_period :=
        Alpha_context.Voting_period.get_current vi.(info.ctxt) in
      let? '_ :=
        check_period_index
          current_period.(Alpha_context.Voting_period.voting_period.index)
          period in
      let? '_ := check_period_kind_for_ballot current_period in
      let? '_ := check_current_proposal vi.(info.ctxt) proposal in
      let? '_ := check_source_has_not_already_voted vi.(info.ctxt) source in
      let? '_ := check_in_listings vi.(info.ctxt) source in
      Error_monad.when_ check_signature
        (fun (function_parameter : unit) ⇒
          let '_ := function_parameter in
          let? public_key :=
            Alpha_context.Contract.get_manager_key None vi.(info.ctxt) source in
          Alpha_context.Operation.check_signature public_key vi.(info.chain_id)
            operation)
    | _unreachable_gadt_branch
    end.

Check that a Ballot operation is compatible with previously validated operations in the current block/mempool.
@return [Error Operation_conflict] if the current block/mempool already contains a Ballot operation from the same source.
  Definition check_ballot_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Ballot {|
          Alpha_context.contents.Ballot.source := source |}) ⇒
      match
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.find_opt)
          source
          vs.(operation_conflict_state.voting_state).(voting_state.ballots_seen)
        with
      | Noneok_unit
      | Some existing
        Pervasives.Error
          (Validate_errors.Operation_conflict
            {|
              Validate_errors.operation_conflict.Operation_conflict.existing :=
                existing;
              Validate_errors.operation_conflict.Operation_conflict.new_operation
                := oph; |})
      end
    | _unreachable_gadt_branch
    end.

  Definition wrap_ballot_conflict
    (function_parameter :
      Pervasives.result unit Validate_errors.operation_conflict) : M? unit :=
    match function_parameter with
    | Pervasives.Ok _ok_unit
    | Pervasives.Error conflict
      Error_monad.error_value
        (Build_extensible "Conflicting_ballot"
          Validate_errors.operation_conflict conflict)
    end.

  Definition add_ballot
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Ballot {|
          Alpha_context.contents.Ballot.source := source |}) ⇒
      let ballots_seen :=
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.add)
          source oph
          vs.(operation_conflict_state.voting_state).(voting_state.ballots_seen)
        in
      let voting_state :=
        voting_state.with_ballots_seen ballots_seen
          vs.(operation_conflict_state.voting_state) in
      operation_conflict_state.with_voting_state voting_state vs
    | _unreachable_gadt_branch
    end.

  Definition remove_ballot
    (vs : operation_conflict_state) (operation : Alpha_context.operation)
    : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Ballot {|
          Alpha_context.contents.Ballot.source := source |}) ⇒
      let ballots_seen :=
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.remove)
          source
          vs.(operation_conflict_state.voting_state).(voting_state.ballots_seen)
        in
      operation_conflict_state.with_voting_state
        (voting_state.with_ballots_seen ballots_seen
          vs.(operation_conflict_state.voting_state)) vs
    | _unreachable_gadt_branch
    end.
End Voting.

Module Anonymous.
  Definition check_activate_account
    (vi : info) (operation : Alpha_context.operation) : M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Activate_account {|
          Alpha_context.contents.Activate_account.id := edpkh;
            Alpha_context.contents.Activate_account.activation_code :=
              activation_code
            |}) ⇒
      let blinded_pkh :=
        Blinded_public_key_hash.of_ed25519_pkh activation_code edpkh in
      let _exists := Alpha_context.Commitment._exists vi.(info.ctxt) blinded_pkh
        in
      let? '_ :=
        Error_monad.error_unless _exists
          (Build_extensible "Invalid_activation"
            Validate_errors.Anonymous.Invalid_activation
            {| Validate_errors.Anonymous.Invalid_activation.pkh := edpkh; |}) in
      Error_monad.Lwt_result_syntax.return_unit
    | _unreachable_gadt_branch
    end.

  Definition check_activate_account_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Activate_account {|
          Alpha_context.contents.Activate_account.id := edpkh |}) ⇒
      match
        Ed25519.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.find_opt)
          edpkh
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.activation_pkhs_seen)
        with
      | Noneok_unit
      | Some existing
        Pervasives.Error
          (Validate_errors.Operation_conflict
            {|
              Validate_errors.operation_conflict.Operation_conflict.existing :=
                existing;
              Validate_errors.operation_conflict.Operation_conflict.new_operation
                := oph; |})
      end
    | _unreachable_gadt_branch
    end.

  Definition wrap_activate_account_conflict
    (operation : Alpha_context.operation)
    (function_parameter :
      Pervasives.result unit Validate_errors.operation_conflict) : M? unit :=
    match function_parameter with
    | Pervasives.Ok _ok_unit
    | Pervasives.Error conflict
      match
        operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
        with
      |
        Alpha_context.Single
          (Alpha_context.Activate_account {|
            Alpha_context.contents.Activate_account.id := edpkh |}) ⇒
        Error_monad.error_value
          (Build_extensible "Conflicting_activation"
            Validate_errors.Anonymous.Conflicting_activation
            {| Validate_errors.Anonymous.Conflicting_activation.edpkh := edpkh;
              Validate_errors.Anonymous.Conflicting_activation.conflict :=
                conflict; |})
      | _unreachable_gadt_branch
      end
    end.

  Definition add_activate_account
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Activate_account {|
          Alpha_context.contents.Activate_account.id := edpkh |}) ⇒
      let activation_pkhs_seen :=
        Ed25519.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.add)
          edpkh oph
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.activation_pkhs_seen)
        in
      operation_conflict_state.with_anonymous_state
        (anonymous_state.with_activation_pkhs_seen activation_pkhs_seen
          vs.(operation_conflict_state.anonymous_state)) vs
    | _unreachable_gadt_branch
    end.

  Definition remove_activate_account
    (vs : operation_conflict_state) (operation : Alpha_context.operation)
    : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Activate_account {|
          Alpha_context.contents.Activate_account.id := edpkh |}) ⇒
      let activation_pkhs_seen :=
        Ed25519.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.remove)
          edpkh
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.activation_pkhs_seen)
        in
      operation_conflict_state.with_anonymous_state
        (anonymous_state.with_activation_pkhs_seen activation_pkhs_seen
          vs.(operation_conflict_state.anonymous_state)) vs
    | _unreachable_gadt_branch
    end.

  Definition check_denunciation_age
    (vi : info) (kind_value : Validate_errors.Anonymous.denunciation_kind)
    (given_level : Alpha_context.Raw_level.t) : M? unit :=
    let current_cycle := vi.(info.current_level).(Alpha_context.Level.t.cycle)
      in
    let? res := Alpha_context.Level.from_raw vi.(info.ctxt) given_level in
    let given_cycle := res.(Alpha_context.Level.t.cycle) in
    let max_slashing_period :=
      Alpha_context.Constants.max_slashing_period vi.(info.ctxt) in
    let? last_slashable_cycle :=
      Alpha_context.Cycle.add given_cycle max_slashing_period in
    let? '_ :=
      Error_monad.error_unless
        (Alpha_context.Cycle.op_lteq given_cycle current_cycle)
        (Build_extensible "Too_early_denunciation"
          Validate_errors.Anonymous.Too_early_denunciation
          {|
            Validate_errors.Anonymous.Too_early_denunciation.kind := kind_value;
            Validate_errors.Anonymous.Too_early_denunciation.level :=
              given_level;
            Validate_errors.Anonymous.Too_early_denunciation.current :=
              vi.(info.current_level).(Alpha_context.Level.t.level); |}) in
    Error_monad.error_unless
      (Alpha_context.Cycle.op_gt last_slashable_cycle current_cycle)
      (Build_extensible "Outdated_denunciation"
        Validate_errors.Anonymous.Outdated_denunciation
        {| Validate_errors.Anonymous.Outdated_denunciation.kind := kind_value;
          Validate_errors.Anonymous.Outdated_denunciation.level := given_level;
          Validate_errors.Anonymous.Outdated_denunciation.last_cycle :=
            last_slashable_cycle; |}).

  Definition check_double_endorsing_evidence
    (denunciation_kind : Validate_errors.Anonymous.denunciation_kind)
    (vi : info) (op1 : Alpha_context.Operation.t)
    (op2 : Alpha_context.Operation.t) : M? unit :=
    match
      (op1.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents),
        op2.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents))
      with
    |
      ((Alpha_context.Single (Alpha_context.Preendorsement e1),
        Alpha_context.Single (Alpha_context.Preendorsement e2)) |
      (Alpha_context.Single (Alpha_context.Endorsement e1),
        Alpha_context.Single (Alpha_context.Endorsement e2))) ⇒
      let op1_hash := Alpha_context.Operation.hash_value op1 in
      let op2_hash := Alpha_context.Operation.hash_value op2 in
      let? '_ :=
        Error_monad.error_unless
          ((Alpha_context.Raw_level.op_eq
            e1.(Alpha_context.consensus_content.level)
            e2.(Alpha_context.consensus_content.level)) &&
          ((Alpha_context.Round.op_eq e1.(Alpha_context.consensus_content.round)
            e2.(Alpha_context.consensus_content.round)) &&
          ((Pervasives.not
            (Block_payload_hash.equal
              e1.(Alpha_context.consensus_content.block_payload_hash)
              e2.(Alpha_context.consensus_content.block_payload_hash))) &&
          (Operation_hash.op_lt op1_hash op2_hash))))
          (Build_extensible "Invalid_denunciation"
            Validate_errors.Anonymous.denunciation_kind denunciation_kind) in
      let? level :=
        Alpha_context.Level.from_raw vi.(info.ctxt)
          e1.(Alpha_context.consensus_content.level) in
      let? '_ :=
        check_denunciation_age vi denunciation_kind
          level.(Alpha_context.Level.t.level) in
      let? '(ctxt, consensus_key1) :=
        Alpha_context.Stake_distribution.slot_owner vi.(info.ctxt) level
          e1.(Alpha_context.consensus_content.slot) in
      let? '(ctxt, consensus_key2) :=
        Alpha_context.Stake_distribution.slot_owner ctxt level
          e2.(Alpha_context.consensus_content.slot) in
      let '(delegate1, delegate2) :=
        (consensus_key1.(Raw_context.consensus_pk.delegate),
          consensus_key2.(Raw_context.consensus_pk.delegate)) in
      let? '_ :=
        Error_monad.error_unless
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.equal)
            delegate1 delegate2)
          (Build_extensible "Inconsistent_denunciation"
            Validate_errors.Anonymous.Inconsistent_denunciation
            {|
              Validate_errors.Anonymous.Inconsistent_denunciation.kind :=
                denunciation_kind;
              Validate_errors.Anonymous.Inconsistent_denunciation.delegate1 :=
                delegate1;
              Validate_errors.Anonymous.Inconsistent_denunciation.delegate2 :=
                delegate2; |}) in
      let '(delegate_pk, delegate) :=
        (consensus_key1.(Raw_context.consensus_pk.consensus_pk), delegate1) in
      let? already_slashed :=
        Alpha_context.Delegate.already_slashed_for_double_endorsing ctxt
          delegate level in
      let? '_ :=
        Error_monad.error_unless (Pervasives.not already_slashed)
          (Build_extensible "Already_denounced"
            Validate_errors.Anonymous.Already_denounced
            {|
              Validate_errors.Anonymous.Already_denounced.kind :=
                denunciation_kind;
              Validate_errors.Anonymous.Already_denounced.delegate := delegate;
              Validate_errors.Anonymous.Already_denounced.level := level; |}) in
      let? '_ :=
        Alpha_context.Operation.check_signature delegate_pk vi.(info.chain_id)
          op1 in
      let? '_ :=
        Alpha_context.Operation.check_signature delegate_pk vi.(info.chain_id)
          op2 in
      Error_monad.Lwt_result_syntax.return_unit
    | _unreachable_gadt_branch
    end.

  Definition check_double_preendorsement_evidence
    (vi : info) (operation : Alpha_context.operation) : M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_preendorsement_evidence {|
          Alpha_context.contents.Double_preendorsement_evidence.op1 := op1;
            Alpha_context.contents.Double_preendorsement_evidence.op2 := op2
            |}) ⇒
      check_double_endorsing_evidence Validate_errors.Anonymous.Preendorsement
        vi op1 op2
    | _unreachable_gadt_branch
    end.

  Definition check_double_endorsement_evidence
    (vi : info) (operation : Alpha_context.operation) : M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_endorsement_evidence {|
          Alpha_context.contents.Double_endorsement_evidence.op1 := op1;
            Alpha_context.contents.Double_endorsement_evidence.op2 := op2
            |}) ⇒
      check_double_endorsing_evidence Validate_errors.Anonymous.Endorsement vi
        op1 op2
    | _unreachable_gadt_branch
    end.

  Definition check_double_endorsing_evidence_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (op1 : Alpha_context.Operation.t)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      op1.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      (Alpha_context.Single (Alpha_context.Preendorsement e1) |
      Alpha_context.Single (Alpha_context.Endorsement e1)) ⇒
      match
        Double_endorsing_evidence_map.(S.INDEXES_MAP.find)
          (e1.(Alpha_context.consensus_content.level),
            e1.(Alpha_context.consensus_content.round),
            e1.(Alpha_context.consensus_content.slot))
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.double_endorsing_evidences_seen)
        with
      | Noneok_unit
      | Some existing
        Pervasives.Error
          (Validate_errors.Operation_conflict
            {|
              Validate_errors.operation_conflict.Operation_conflict.existing :=
                existing;
              Validate_errors.operation_conflict.Operation_conflict.new_operation
                := oph; |})
      end
    | _unreachable_gadt_branch
    end.

  Definition check_double_preendorsement_evidence_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_preendorsement_evidence {|
          Alpha_context.contents.Double_preendorsement_evidence.op1 := op1
            |}) ⇒ check_double_endorsing_evidence_conflict vs oph op1
    | _unreachable_gadt_branch
    end.

  Definition check_double_endorsement_evidence_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_endorsement_evidence {|
          Alpha_context.contents.Double_endorsement_evidence.op1 := op1 |})
      ⇒ check_double_endorsing_evidence_conflict vs oph op1
    | _unreachable_gadt_branch
    end.

  Definition wrap_denunciation_conflict
    (kind_value : Validate_errors.Anonymous.denunciation_kind)
    (function_parameter :
      Pervasives.result unit Validate_errors.operation_conflict) : M? unit :=
    match function_parameter with
    | Pervasives.Ok _ok_unit
    | Pervasives.Error conflict
      Error_monad.error_value
        (Build_extensible "Conflicting_denunciation"
          Validate_errors.Anonymous.Conflicting_denunciation
          {|
            Validate_errors.Anonymous.Conflicting_denunciation.kind :=
              kind_value;
            Validate_errors.Anonymous.Conflicting_denunciation.conflict :=
              conflict; |})
    end.

  Definition add_double_endorsing_evidence
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (op1 : Alpha_context.Operation.t) : operation_conflict_state :=
    match
      op1.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      (Alpha_context.Single (Alpha_context.Preendorsement e1) |
      Alpha_context.Single (Alpha_context.Endorsement e1)) ⇒
      let double_endorsing_evidences_seen :=
        Double_endorsing_evidence_map.(S.INDEXES_MAP.add)
          (e1.(Alpha_context.consensus_content.level),
            e1.(Alpha_context.consensus_content.round),
            e1.(Alpha_context.consensus_content.slot)) oph
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.double_endorsing_evidences_seen)
        in
      operation_conflict_state.with_anonymous_state
        (anonymous_state.with_double_endorsing_evidences_seen
          double_endorsing_evidences_seen
          vs.(operation_conflict_state.anonymous_state)) vs
    | _unreachable_gadt_branch
    end.

  Definition add_double_endorsement_evidence
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_endorsement_evidence {|
          Alpha_context.contents.Double_endorsement_evidence.op1 := op1 |})
      ⇒ add_double_endorsing_evidence vs oph op1
    | _unreachable_gadt_branch
    end.

  Definition add_double_preendorsement_evidence
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_preendorsement_evidence {|
          Alpha_context.contents.Double_preendorsement_evidence.op1 := op1
            |}) ⇒ add_double_endorsing_evidence vs oph op1
    | _unreachable_gadt_branch
    end.

  Definition remove_double_endorsing_evidence
    (vs : operation_conflict_state) (op : Alpha_context.Operation.t)
    : operation_conflict_state :=
    match
      op.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      (Alpha_context.Single (Alpha_context.Endorsement e_value) |
      Alpha_context.Single (Alpha_context.Preendorsement e_value)) ⇒
      let double_endorsing_evidences_seen :=
        Double_endorsing_evidence_map.(S.INDEXES_MAP.remove)
          (e_value.(Alpha_context.consensus_content.level),
            e_value.(Alpha_context.consensus_content.round),
            e_value.(Alpha_context.consensus_content.slot))
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.double_endorsing_evidences_seen)
        in
      let anonymous_state :=
        anonymous_state.with_double_endorsing_evidences_seen
          double_endorsing_evidences_seen
          vs.(operation_conflict_state.anonymous_state) in
      operation_conflict_state.with_anonymous_state anonymous_state vs
    | _unreachable_gadt_branch
    end.

  Definition remove_double_preendorsement_evidence
    (vs : operation_conflict_state) (operation : Alpha_context.operation)
    : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_preendorsement_evidence {|
          Alpha_context.contents.Double_preendorsement_evidence.op1 := op1
            |}) ⇒ remove_double_endorsing_evidence vs op1
    | _unreachable_gadt_branch
    end.

  Definition remove_double_endorsement_evidence
    (vs : operation_conflict_state) (operation : Alpha_context.operation)
    : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_endorsement_evidence {|
          Alpha_context.contents.Double_endorsement_evidence.op1 := op1 |})
      ⇒ remove_double_endorsing_evidence vs op1
    | _unreachable_gadt_branch
    end.

  Definition check_double_baking_evidence
    (vi : info) (operation : Alpha_context.operation) : M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_baking_evidence {|
          Alpha_context.contents.Double_baking_evidence.bh1 := bh1;
            Alpha_context.contents.Double_baking_evidence.bh2 := bh2
            |}) ⇒
      let hash1 := Alpha_context.Block_header.hash_value bh1 in
      let hash2 := Alpha_context.Block_header.hash_value bh2 in
      let? bh1_fitness :=
        Alpha_context.Fitness.from_raw
          bh1.(Alpha_context.Block_header.t.shell).(Block_header.shell_header.fitness)
        in
      let round1 := Alpha_context.Fitness.round bh1_fitness in
      let? bh2_fitness :=
        Alpha_context.Fitness.from_raw
          bh2.(Alpha_context.Block_header.t.shell).(Block_header.shell_header.fitness)
        in
      let round2 := Alpha_context.Fitness.round bh2_fitness in
      let? level1 :=
        Alpha_context.Raw_level.of_int32
          bh1.(Alpha_context.Block_header.t.shell).(Block_header.shell_header.level)
        in
      let? level2 :=
        Alpha_context.Raw_level.of_int32
          bh2.(Alpha_context.Block_header.t.shell).(Block_header.shell_header.level)
        in
      let? '_ :=
        Error_monad.error_unless
          ((Alpha_context.Raw_level.op_eq level1 level2) &&
          ((Alpha_context.Round.op_eq round1 round2) &&
          (Block_hash.op_lt hash1 hash2)))
          (Build_extensible "Invalid_double_baking_evidence"
            Validate_errors.Anonymous.Invalid_double_baking_evidence
            {|
              Validate_errors.Anonymous.Invalid_double_baking_evidence.hash1 :=
                hash1;
              Validate_errors.Anonymous.Invalid_double_baking_evidence.level1 :=
                level1;
              Validate_errors.Anonymous.Invalid_double_baking_evidence.round1 :=
                round1;
              Validate_errors.Anonymous.Invalid_double_baking_evidence.hash2 :=
                hash2;
              Validate_errors.Anonymous.Invalid_double_baking_evidence.level2 :=
                level2;
              Validate_errors.Anonymous.Invalid_double_baking_evidence.round2 :=
                round2; |}) in
      let? '_ :=
        check_denunciation_age vi Validate_errors.Anonymous.Block level1 in
      let? level := Alpha_context.Level.from_raw vi.(info.ctxt) level1 in
      let committee_size :=
        Alpha_context.Constants.consensus_committee_size vi.(info.ctxt) in
      let? slot1 := Alpha_context.Round.to_slot round1 committee_size in
      let? '(ctxt, consensus_key1) :=
        Alpha_context.Stake_distribution.slot_owner vi.(info.ctxt) level slot1
        in
      let? slot2 := Alpha_context.Round.to_slot round2 committee_size in
      let? '(ctxt, consensus_key2) :=
        Alpha_context.Stake_distribution.slot_owner ctxt level slot2 in
      let '(delegate1, delegate2) :=
        (consensus_key1.(Raw_context.consensus_pk.delegate),
          consensus_key2.(Raw_context.consensus_pk.delegate)) in
      let? '_ :=
        Error_monad.error_unless
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.op_eq)
            delegate1 delegate2)
          (Build_extensible "Inconsistent_denunciation"
            Validate_errors.Anonymous.Inconsistent_denunciation
            {|
              Validate_errors.Anonymous.Inconsistent_denunciation.kind :=
                Validate_errors.Anonymous.Block;
              Validate_errors.Anonymous.Inconsistent_denunciation.delegate1 :=
                delegate1;
              Validate_errors.Anonymous.Inconsistent_denunciation.delegate2 :=
                delegate2; |}) in
      let '(delegate_pk, delegate) :=
        (consensus_key1.(Raw_context.consensus_pk.consensus_pk), delegate1) in
      let? already_slashed :=
        Alpha_context.Delegate.already_slashed_for_double_baking ctxt delegate
          level in
      let? '_ :=
        Error_monad.error_unless (Pervasives.not already_slashed)
          (Build_extensible "Already_denounced"
            Validate_errors.Anonymous.Already_denounced
            {|
              Validate_errors.Anonymous.Already_denounced.kind :=
                Validate_errors.Anonymous.Block;
              Validate_errors.Anonymous.Already_denounced.delegate := delegate;
              Validate_errors.Anonymous.Already_denounced.level := level; |}) in
      let? '_ :=
        Alpha_context.Block_header.check_signature bh1 vi.(info.chain_id)
          delegate_pk in
      let? '_ :=
        Alpha_context.Block_header.check_signature bh2 vi.(info.chain_id)
          delegate_pk in
      Error_monad.Lwt_result_syntax.return_unit
    | _unreachable_gadt_branch
    end.

  Definition check_double_baking_evidence_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_baking_evidence {|
          Alpha_context.contents.Double_baking_evidence.bh1 := bh1 |}) ⇒
      let bh1_fitness :=
        (fun (function_parameter : M? Alpha_context.Fitness.t) ⇒
          match function_parameter with
          | Pervasives.Ok f_valuef_value
          | Pervasives.Error _
            (* ❌ Assert instruction is not handled. *)
            assert Alpha_context.Fitness.t false
          end)
          (Alpha_context.Fitness.from_raw
            bh1.(Alpha_context.Block_header.t.shell).(Block_header.shell_header.fitness))
        in
      let round := Alpha_context.Fitness.round bh1_fitness in
      let level := Alpha_context.Fitness.level bh1_fitness in
      match
        Double_baking_evidence_map.(S.INDEXES_MAP.find) (level, round)
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.double_baking_evidences_seen)
        with
      | Noneok_unit
      | Some existing
        Pervasives.Error
          (Validate_errors.Operation_conflict
            {|
              Validate_errors.operation_conflict.Operation_conflict.existing :=
                existing;
              Validate_errors.operation_conflict.Operation_conflict.new_operation
                := oph; |})
      end
    | _unreachable_gadt_branch
    end.

  Definition add_double_baking_evidence
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_baking_evidence {|
          Alpha_context.contents.Double_baking_evidence.bh1 := bh1 |}) ⇒
      let bh1_fitness :=
        (fun (function_parameter : M? Alpha_context.Fitness.t) ⇒
          match function_parameter with
          | Pervasives.Ok f_valuef_value
          | Pervasives.Error _
            (* ❌ Assert instruction is not handled. *)
            assert Alpha_context.Fitness.t false
          end)
          (Alpha_context.Fitness.from_raw
            bh1.(Alpha_context.Block_header.t.shell).(Block_header.shell_header.fitness))
        in
      let round := Alpha_context.Fitness.round bh1_fitness in
      let level := Alpha_context.Fitness.level bh1_fitness in
      let double_baking_evidences_seen :=
        Double_baking_evidence_map.(S.INDEXES_MAP.add) (level, round) oph
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.double_baking_evidences_seen)
        in
      operation_conflict_state.with_anonymous_state
        (anonymous_state.with_double_baking_evidences_seen
          double_baking_evidences_seen
          vs.(operation_conflict_state.anonymous_state)) vs
    | _unreachable_gadt_branch
    end.

  Definition remove_double_baking_evidence
    (vs : operation_conflict_state) (operation : Alpha_context.operation)
    : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Double_baking_evidence {|
          Alpha_context.contents.Double_baking_evidence.bh1 := bh1 |}) ⇒
      let '(bh1_fitness, level) :=
        match
          ((Alpha_context.Fitness.from_raw
            bh1.(Alpha_context.Block_header.t.shell).(Block_header.shell_header.fitness)),
            (Alpha_context.Raw_level.of_int32
              bh1.(Alpha_context.Block_header.t.shell).(Block_header.shell_header.level)))
          with
        | (Pervasives.Ok v_value, Pervasives.Ok v')(v_value, v')
        | _
          (* ❌ Assert instruction is not handled. *)
          assert (Alpha_context.Fitness.t × Alpha_context.Raw_level.raw_level)
            false
        end in
      let round := Alpha_context.Fitness.round bh1_fitness in
      let double_baking_evidences_seen :=
        Double_baking_evidence_map.(S.INDEXES_MAP.remove) (level, round)
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.double_baking_evidences_seen)
        in
      let anonymous_state :=
        anonymous_state.with_double_baking_evidences_seen
          double_baking_evidences_seen
          vs.(operation_conflict_state.anonymous_state) in
      operation_conflict_state.with_anonymous_state anonymous_state vs
    | _unreachable_gadt_branch
    end.

  Definition check_drain_delegate
    (info_value : info) (check_signature : bool)
    (operation : Alpha_context.Operation.t) : M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Drain_delegate {|
          Alpha_context.contents.Drain_delegate.consensus_key := consensus_key;
            Alpha_context.contents.Drain_delegate.delegate := delegate;
            Alpha_context.contents.Drain_delegate.destination := destination
            |}) ⇒
      let is_registered :=
        Alpha_context.Delegate.registered info_value.(info.ctxt) delegate in
      let? '_ :=
        Error_monad.fail_unless is_registered
          (Build_extensible "Drain_delegate_on_unregistered_delegate"
            Signature.public_key_hash delegate) in
      let? active_pk :=
        Alpha_context.Delegate.Consensus_key.active_pubkey
          info_value.(info.ctxt) delegate in
      let? '_ :=
        Error_monad.fail_unless
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.equal)
            active_pk.(Raw_context.consensus_pk.consensus_pkh) consensus_key)
          (Build_extensible "Invalid_drain_delegate_inactive_key"
            Validate_errors.Anonymous.Invalid_drain_delegate_inactive_key
            {|
              Validate_errors.Anonymous.Invalid_drain_delegate_inactive_key.delegate
                := delegate;
              Validate_errors.Anonymous.Invalid_drain_delegate_inactive_key.consensus_key
                := consensus_key;
              Validate_errors.Anonymous.Invalid_drain_delegate_inactive_key.active_consensus_key
                := active_pk.(Raw_context.consensus_pk.consensus_pkh); |}) in
      let? '_ :=
        Error_monad.fail_when
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.equal)
            active_pk.(Raw_context.consensus_pk.consensus_pkh) delegate)
          (Build_extensible "Invalid_drain_delegate_no_consensus_key"
            Signature.public_key_hash delegate) in
      let? '_ :=
        Error_monad.fail_when
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.equal)
            destination delegate)
          (Build_extensible "Invalid_drain_delegate_noop"
            Signature.public_key_hash delegate) in
      let is_destination_allocated :=
        Alpha_context.Contract.allocated info_value.(info.ctxt)
          (Contract_repr.Implicit destination) in
      let? balance :=
        Alpha_context.Contract.get_balance info_value.(info.ctxt)
          (Contract_repr.Implicit delegate) in
      let? origination_burn :=
        if is_destination_allocated then
          return? Alpha_context.Tez.zero
        else
          let cost_per_byte :=
            Alpha_context.Constants.cost_per_byte info_value.(info.ctxt) in
          let origination_size :=
            Alpha_context.Constants.origination_size info_value.(info.ctxt) in
          Alpha_context.Tez.op_starquestion cost_per_byte
            (Int64.of_int origination_size) in
      let? drain_fees :=
        let? one_percent := Alpha_context.Tez.op_divquestion balance 100 in
        return? (Alpha_context.Tez.max Alpha_context.Tez.one one_percent) in
      let? min_amount :=
        Alpha_context.Tez.op_plusquestion origination_burn drain_fees in
      let? '_ :=
        Error_monad.fail_when (Alpha_context.Tez.op_lt balance min_amount)
          (Build_extensible
            "Invalid_drain_delegate_insufficient_funds_for_burn_or_fees"
            Validate_errors.Anonymous.Invalid_drain_delegate_insufficient_funds_for_burn_or_fees
            {|
              Validate_errors.Anonymous.Invalid_drain_delegate_insufficient_funds_for_burn_or_fees.delegate
                := delegate;
              Validate_errors.Anonymous.Invalid_drain_delegate_insufficient_funds_for_burn_or_fees.destination
                := destination;
              Validate_errors.Anonymous.Invalid_drain_delegate_insufficient_funds_for_burn_or_fees.min_amount
                := min_amount; |}) in
      let? '_ :=
        if check_signature then
          Alpha_context.Operation.check_signature
            active_pk.(Raw_context.consensus_pk.consensus_pk)
            info_value.(info.chain_id) operation
        else
          ok_unit in
      Error_monad.Lwt_result_syntax.return_unit
    | _unreachable_gadt_branch
    end.

  Definition check_drain_delegate_conflict
    (state_value : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.Operation.t)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Drain_delegate {|
          Alpha_context.contents.Drain_delegate.delegate := delegate |}) ⇒
      match
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.find_opt)
          delegate
          state_value.(operation_conflict_state.manager_state).(manager_state.managers_seen)
        with
      | Noneok_unit
      | Some existing
        Pervasives.Error
          (Validate_errors.Operation_conflict
            {|
              Validate_errors.operation_conflict.Operation_conflict.existing :=
                existing;
              Validate_errors.operation_conflict.Operation_conflict.new_operation
                := oph; |})
      end
    | _unreachable_gadt_branch
    end.

  Definition wrap_drain_delegate_conflict
    (operation : Alpha_context.Operation.t)
    : Pervasives.result unit Validate_errors.operation_conflict M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Drain_delegate {|
          Alpha_context.contents.Drain_delegate.delegate := delegate |}) ⇒
      fun (function_parameter :
        Pervasives.result unit Validate_errors.operation_conflict) ⇒
        match function_parameter with
        | Pervasives.Ok _ok_unit
        | Pervasives.Error conflict
          Error_monad.error_value
            (Build_extensible "Conflicting_drain_delegate"
              Validate_errors.Anonymous.Conflicting_drain_delegate
              {|
                Validate_errors.Anonymous.Conflicting_drain_delegate.delegate :=
                  delegate;
                Validate_errors.Anonymous.Conflicting_drain_delegate.conflict :=
                  conflict; |})
        end
    | _unreachable_gadt_branch
    end.

  Definition add_drain_delegate
    (state_value : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.Operation.t) : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Drain_delegate {|
          Alpha_context.contents.Drain_delegate.delegate := delegate |}) ⇒
      let managers_seen :=
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.add)
          delegate oph
          state_value.(operation_conflict_state.manager_state).(manager_state.managers_seen)
        in
      operation_conflict_state.with_manager_state
        {| manager_state.managers_seen := managers_seen; |} state_value
    | _unreachable_gadt_branch
    end.

  Definition remove_drain_delegate
    (state_value : operation_conflict_state)
    (operation : Alpha_context.Operation.t) : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Drain_delegate {|
          Alpha_context.contents.Drain_delegate.delegate := delegate |}) ⇒
      let managers_seen :=
        Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.remove)
          delegate
          state_value.(operation_conflict_state.manager_state).(manager_state.managers_seen)
        in
      operation_conflict_state.with_manager_state
        {| manager_state.managers_seen := managers_seen; |} state_value
    | _unreachable_gadt_branch
    end.

  Definition check_seed_nonce_revelation
    (vi : info) (operation : Alpha_context.operation) : M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Seed_nonce_revelation {|
          Alpha_context.contents.Seed_nonce_revelation.level := commitment_raw_level;
            Alpha_context.contents.Seed_nonce_revelation.nonce := nonce_value
            |}) ⇒
      let? commitment_level :=
        Alpha_context.Level.from_raw vi.(info.ctxt) commitment_raw_level in
      let? '_ :=
        Alpha_context.Nonce.check_unrevealed vi.(info.ctxt) commitment_level
          nonce_value in
      Error_monad.Lwt_result_syntax.return_unit
    | _unreachable_gadt_branch
    end.

  Definition check_seed_nonce_revelation_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Seed_nonce_revelation {|
          Alpha_context.contents.Seed_nonce_revelation.level := commitment_raw_level
            |}) ⇒
      match
        Alpha_context.Raw_level.Map.(Map.S.find_opt) commitment_raw_level
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.seed_nonce_levels_seen)
        with
      | Noneok_unit
      | Some existing
        Pervasives.Error
          (Validate_errors.Operation_conflict
            {|
              Validate_errors.operation_conflict.Operation_conflict.existing :=
                existing;
              Validate_errors.operation_conflict.Operation_conflict.new_operation
                := oph; |})
      end
    | _unreachable_gadt_branch
    end.

  Definition wrap_seed_nonce_revelation_conflict
    (function_parameter :
      Pervasives.result unit Validate_errors.operation_conflict) : M? unit :=
    match function_parameter with
    | Pervasives.Ok _ok_unit
    | Pervasives.Error conflict
      Error_monad.error_value
        (Build_extensible "Conflicting_nonce_revelation"
          Validate_errors.operation_conflict conflict)
    end.

  Definition add_seed_nonce_revelation
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Seed_nonce_revelation {|
          Alpha_context.contents.Seed_nonce_revelation.level := commitment_raw_level
            |}) ⇒
      let seed_nonce_levels_seen :=
        Alpha_context.Raw_level.Map.(Map.S.add) commitment_raw_level oph
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.seed_nonce_levels_seen)
        in
      let anonymous_state :=
        anonymous_state.with_seed_nonce_levels_seen seed_nonce_levels_seen
          vs.(operation_conflict_state.anonymous_state) in
      operation_conflict_state.with_anonymous_state anonymous_state vs
    | _unreachable_gadt_branch
    end.

  Definition remove_seed_nonce_revelation
    (vs : operation_conflict_state) (operation : Alpha_context.operation)
    : operation_conflict_state :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Seed_nonce_revelation {|
          Alpha_context.contents.Seed_nonce_revelation.level := commitment_raw_level
            |}) ⇒
      let seed_nonce_levels_seen :=
        Alpha_context.Raw_level.Map.(Map.S.remove) commitment_raw_level
          vs.(operation_conflict_state.anonymous_state).(anonymous_state.seed_nonce_levels_seen)
        in
      let anonymous_state :=
        anonymous_state.with_seed_nonce_levels_seen seed_nonce_levels_seen
          vs.(operation_conflict_state.anonymous_state) in
      operation_conflict_state.with_anonymous_state anonymous_state vs
    | _unreachable_gadt_branch
    end.

  Definition check_vdf_revelation
    (vi : info) (operation : Alpha_context.operation) : M? unit :=
    match
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      with
    |
      Alpha_context.Single
        (Alpha_context.Vdf_revelation {|
          Alpha_context.contents.Vdf_revelation.solution := solution |}) ⇒
      let? '_ := Alpha_context.Seed.check_vdf vi.(info.ctxt) solution in
      Error_monad.Lwt_result_syntax.return_unit
    | _unreachable_gadt_branch
    end.

  Definition check_vdf_revelation_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    match
      vs.(operation_conflict_state.anonymous_state).(anonymous_state.vdf_solution_seen)
      with
    | Noneok_unit
    | Some existing
      Pervasives.Error
        (Validate_errors.Operation_conflict
          {|
            Validate_errors.operation_conflict.Operation_conflict.existing :=
              existing;
            Validate_errors.operation_conflict.Operation_conflict.new_operation
              := oph; |})
    end.

  Definition wrap_vdf_revelation_conflict
    (function_parameter :
      Pervasives.result unit Validate_errors.operation_conflict) : M? unit :=
    match function_parameter with
    | Pervasives.Ok _ok_unit
    | Pervasives.Error conflict
      Error_monad.error_value
        (Build_extensible "Conflicting_vdf_revelation"
          Validate_errors.operation_conflict conflict)
    end.

  Definition add_vdf_revelation
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    : operation_conflict_state :=
    operation_conflict_state.with_anonymous_state
      (anonymous_state.with_vdf_solution_seen (Some oph)
        vs.(operation_conflict_state.anonymous_state)) vs.

  Definition remove_vdf_revelation (vs : operation_conflict_state)
    : operation_conflict_state :=
    let anonymous_state :=
      anonymous_state.with_vdf_solution_seen None
        vs.(operation_conflict_state.anonymous_state) in
    operation_conflict_state.with_anonymous_state anonymous_state vs.
End Anonymous.

Module Manager.
State that simulates changes from individual operations that have an effect on future operations inside the same batch.
  Module batch_state.
    Record record : Set := Build {
      balance : Alpha_context.Tez.t;
      is_allocated : bool;
      total_gas_used : Alpha_context.Gas.Arith.fp;
    }.
    Definition with_balance balance (r : record) :=
      Build balance r.(is_allocated) r.(total_gas_used).
    Definition with_is_allocated is_allocated (r : record) :=
      Build r.(balance) is_allocated r.(total_gas_used).
    Definition with_total_gas_used total_gas_used (r : record) :=
      Build r.(balance) r.(is_allocated) total_gas_used.
  End batch_state.
  Definition batch_state := batch_state.record.

Check a few simple properties of the batch, and return the initial {!batch_state} and the contract public key.
Invariants checked: - All operations in a batch have the same source. - The source's contract is allocated. - The counters in a batch are successive, and the first of them is the source's next expected counter. - A batch contains at most one Reveal operation that must occur in first position. - The source's public key has been revealed (either before the considered batch, or during its first operation).
Note that currently, the [op] batch contains only one signature, so all operations in the batch are required to originate from the same manager. This may change in the future, in order to allow several managers to group-sign a sequence of operations.
  Definition check_sanity_and_find_public_key
    (vi : info) (contents_list : Alpha_context.contents_list)
    : M? (batch_state × Alpha_context.public_key) :=
    let check_source_and_counter
      (expected_source : Signature.public_key_hash)
      (source : Signature.public_key_hash)
      (previous_counter : Alpha_context.Manager_counter.t)
      (counter : Alpha_context.Manager_counter.t) : M? unit :=
      let? '_ :=
        Error_monad.error_unless
          (Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.equal)
            expected_source source)
          (Build_extensible "Inconsistent_sources" unit tt) in
      Error_monad.error_unless
        (Alpha_context.Manager_counter.op_eq
          (Alpha_context.Manager_counter.succ previous_counter) counter)
        (Build_extensible "Inconsistent_counters" unit tt) in
    let fix check_batch_tail_sanity
      (expected_source : Alpha_context.public_key_hash)
      (previous_counter : Alpha_context.Manager_counter.t)
      (function_parameter : Alpha_context.contents_list) : M? unit :=
      match function_parameter with
      |
        Alpha_context.Single
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.operation :=
              Alpha_context.Reveal _key
              |}) ⇒
        Error_monad.error_value
          (Build_extensible "Incorrect_reveal_position" unit tt)
      |
        Alpha_context.Cons
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.operation :=
              Alpha_context.Reveal _key
              |}) _res
        Error_monad.error_value
          (Build_extensible "Incorrect_reveal_position" unit tt)
      |
        Alpha_context.Single
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source;
              Alpha_context.contents.Manager_operation.counter := counter
              |}) ⇒
        check_source_and_counter expected_source source previous_counter counter
      |
        Alpha_context.Cons
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source;
              Alpha_context.contents.Manager_operation.counter := counter
              |}) rest
        let? '_ :=
          check_source_and_counter expected_source source previous_counter
            counter in
        check_batch_tail_sanity source counter rest
      | _unreachable_gadt_branch
      end in
    let check_batch (contents_list : Alpha_context.contents_list)
      : M?
        (Alpha_context.public_key_hash × option Alpha_context.public_key ×
          Alpha_context.Manager_counter.t) :=
      match contents_list with
      |
        Alpha_context.Single
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source;
              Alpha_context.contents.Manager_operation.counter := counter;
              Alpha_context.contents.Manager_operation.operation :=
                Alpha_context.Reveal key_value
              |}) ⇒ return? (source, (Some key_value), counter)
      |
        Alpha_context.Single
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source;
              Alpha_context.contents.Manager_operation.counter := counter
              |}) ⇒ return? (source, None, counter)
      |
        Alpha_context.Cons
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source;
              Alpha_context.contents.Manager_operation.counter := counter;
              Alpha_context.contents.Manager_operation.operation :=
                Alpha_context.Reveal key_value
              |}) rest
        let? '_ := check_batch_tail_sanity source counter rest in
        return? (source, (Some key_value), counter)
      |
        Alpha_context.Cons
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source;
              Alpha_context.contents.Manager_operation.counter := counter
              |}) rest
        let? '_ := check_batch_tail_sanity source counter rest in
        return? (source, None, counter)
      | _unreachable_gadt_branch
      end in
    let? '(source, revealed_key, first_counter) := check_batch contents_list in
    let? balance :=
      Alpha_context.Contract.check_allocated_and_get_balance vi.(info.ctxt)
        source in
    let? '_ :=
      Alpha_context.Contract.check_counter_increment vi.(info.ctxt) source
        first_counter in
    let? pk :=
      match revealed_key with
      | Some pkreturn? pk
      | None
        Alpha_context.Contract.get_manager_key None vi.(info.ctxt) source
      end in
    let initial_batch_state :=
      {| batch_state.balance := balance; batch_state.is_allocated := true;
        batch_state.total_gas_used := Alpha_context.Gas.Arith.zero; |} in
    return? (initial_batch_state, pk).

  Definition check_gas_limit
    (info_value : info) (gas_limit : Alpha_context.Gas.Arith.integral)
    : M? unit :=
    Alpha_context.Gas.check_gas_limit
      info_value.(info.manager_info).(manager_info.hard_gas_limit_per_operation)
      gas_limit.

  Definition check_storage_limit (vi : info) (storage_limit : Z.t) : M? unit :=
    Error_monad.error_unless
      ((storage_limit Z
      vi.(info.manager_info).(manager_info.hard_storage_limit_per_operation)) &&
      (storage_limit Z Z.zero))
      (Build_extensible "Storage_limit_too_high" unit tt).

  Definition assert_tx_rollup_feature_enabled (vi : info) : M? unit :=
    let? sunset :=
      Alpha_context.Raw_level.of_int32
        (Alpha_context.Constants.tx_rollup_sunset_level vi.(info.ctxt)) in
    Error_monad.error_unless
      ((Alpha_context.Constants.tx_rollup_enable vi.(info.ctxt)) &&
      (Alpha_context.Raw_level.op_lt
        vi.(info.current_level).(Alpha_context.Level.t.level) sunset))
      (Build_extensible "Tx_rollup_feature_disabled" unit tt).

  Definition assert_sc_rollup_feature_enabled (vi : info) : M? unit :=
    Error_monad.error_unless
      (Alpha_context.Constants.sc_rollup_enable vi.(info.ctxt))
      (Build_extensible "Sc_rollup_feature_disabled" unit tt).

  Definition assert_not_zero_messages {A : Set} (messages : list A) : M? unit :=
    match messages with
    | []
      Error_monad.error_value
        (Build_extensible "Sc_rollup_add_zero_messages" unit tt)
    | _ok_unit
    end.

  Definition assert_zk_rollup_feature_enabled (vi : info) : M? unit :=
    Error_monad.error_unless
      (Alpha_context.Constants.zk_rollup_enable vi.(info.ctxt))
      (Build_extensible "Zk_rollup_feature_disabled" unit tt).

  Definition consume_decoding_gas
    (remaining_gas : Alpha_context.Gas.Arith.fp)
    (lexpr : Alpha_context.Script.lazy_expr) : M? Alpha_context.Gas.Arith.fp :=
    Error_monad.record_trace
      (Build_extensible "Gas_quota_exceeded_init_deserialize" unit tt)
      (Alpha_context.Script.consume_decoding_gas remaining_gas lexpr).

  Definition validate_tx_rollup_submit_batch
    (vi : info) (remaining_gas : Alpha_context.Gas.Arith.fp) (content : string)
    : M? unit :=
    let? '_ := assert_tx_rollup_feature_enabled vi in
    let '(_message, message_size) :=
      Alpha_context.Tx_rollup_message.make_batch content in
    let? cost := Tx_rollup_gas.hash_cost message_size in
    let size_limit :=
      Alpha_context.Constants.tx_rollup_hard_size_limit_per_message
        vi.(info.ctxt) in
    let? '_ := Alpha_context.Gas.consume_from remaining_gas cost in
    Error_monad.error_unless (message_size i size_limit)
      (Build_extensible "Message_size_exceeds_limit" unit tt).

  Definition validate_tx_rollup_dispatch_tickets
    (vi : info) (remaining_gas : Alpha_context.Gas.Arith.fp)
    (operation : Alpha_context.manager_operation) : M? unit :=
    let? '_ := assert_tx_rollup_feature_enabled vi in
    match operation with
    |
      Alpha_context.Tx_rollup_dispatch_tickets {|
        Alpha_context.manager_operation.Tx_rollup_dispatch_tickets.message_result_path
          := message_result_path;
          Alpha_context.manager_operation.Tx_rollup_dispatch_tickets.tickets_info
            := tickets_info
          |} ⇒
      let '{|
        Alpha_context.Constants.Parametric.tx_rollup.max_messages_per_inbox :=
          max_messages_per_inbox;
          Alpha_context.Constants.Parametric.tx_rollup.max_withdrawals_per_batch
            := max_withdrawals_per_batch
          |} := Alpha_context.Constants.tx_rollup vi.(info.ctxt) in
      let? '_ :=
        Alpha_context.Tx_rollup_errors.check_path_depth
          Alpha_context.Tx_rollup_errors.Commitment
          (Alpha_context.Tx_rollup_commitment.Merkle.(Merkle_list.T.path_depth)
            message_result_path) max_messages_per_inbox in
      let? '_ :=
        Error_monad.error_when (Compare.List_length_with.op_eq tickets_info 0)
          (Build_extensible "No_withdrawals_to_dispatch" unit tt) in
      let? '_ :=
        Error_monad.error_when
          (Compare.List_length_with.op_gt tickets_info max_withdrawals_per_batch)
          (Build_extensible "Too_many_withdrawals" unit tt) in
      let? '_ :=
        Error_monad.record_trace
          (Build_extensible "Gas_quota_exceeded_init_deserialize" unit tt)
          (List.fold_left_e
            (fun (remaining_gas : Alpha_context.Gas.Arith.fp) ⇒
              fun (function_parameter : Alpha_context.Tx_rollup_reveal.t) ⇒
                let '{|
                  Alpha_context.Tx_rollup_reveal.t.contents := contents;
                    Alpha_context.Tx_rollup_reveal.t.ty := ty_value
                    |} := function_parameter in
                let? remaining_gas :=
                  Alpha_context.Script.consume_decoding_gas remaining_gas
                    contents in
                Alpha_context.Script.consume_decoding_gas remaining_gas ty_value)
            remaining_gas tickets_info) in
      Error_monad.Result_syntax.return_unit
    | _unreachable_gadt_branch
    end.

  Definition validate_tx_rollup_rejection
    (vi : info) (operation : Alpha_context.manager_operation) : M? unit :=
    let? '_ := assert_tx_rollup_feature_enabled vi in
    match operation with
    |
      Alpha_context.Tx_rollup_rejection {|
        Alpha_context.manager_operation.Tx_rollup_rejection.message_path :=
          message_path;
          Alpha_context.manager_operation.Tx_rollup_rejection.message_result_path
            := message_result_path;
          Alpha_context.manager_operation.Tx_rollup_rejection.previous_message_result_path
            := previous_message_result_path
          |} ⇒
      let '{|
        Alpha_context.Constants.Parametric.tx_rollup.max_messages_per_inbox :=
          max_messages_per_inbox
          |} := Alpha_context.Constants.tx_rollup vi.(info.ctxt) in
      let? '_ :=
        Alpha_context.Tx_rollup_errors.check_path_depth
          Alpha_context.Tx_rollup_errors.Inbox
          (Alpha_context.Tx_rollup_inbox.Merkle.path_depth message_path)
          max_messages_per_inbox in
      let? '_ :=
        Alpha_context.Tx_rollup_errors.check_path_depth
          Alpha_context.Tx_rollup_errors.Commitment
          (Alpha_context.Tx_rollup_commitment.Merkle.(Merkle_list.T.path_depth)
            message_result_path) max_messages_per_inbox in
      Alpha_context.Tx_rollup_errors.check_path_depth
        Alpha_context.Tx_rollup_errors.Commitment
        (Alpha_context.Tx_rollup_commitment.Merkle.(Merkle_list.T.path_depth)
          previous_message_result_path) max_messages_per_inbox
    | _unreachable_gadt_branch
    end.

  Definition may_trace_gas_limit_too_high {A : Set} (info_value : info)
    : M? A M? A :=
    match info_value.(info.mode) with
    | (Application _ | Partial_validation _ | Construction _) ⇒
      fun (x_value : M? A) ⇒ x_value
    | Mempool
      Error_monad.record_trace (Build_extensible "Gas_limit_too_high" unit tt)
    end.

  Definition check_contents
    (vi : info) (batch_state_value : batch_state)
    (contents : Alpha_context.contents)
    (remaining_block_gas : Alpha_context.Gas.Arith.t) : M? batch_state :=
    match contents with
    |
      Alpha_context.Manager_operation {|
        Alpha_context.contents.Manager_operation.source := source;
          Alpha_context.contents.Manager_operation.fee := fee;
          Alpha_context.contents.Manager_operation.counter := _;
          Alpha_context.contents.Manager_operation.operation := operation;
          Alpha_context.contents.Manager_operation.gas_limit := gas_limit;
          Alpha_context.contents.Manager_operation.storage_limit :=
            storage_limit
          |} ⇒
      let? '_ := check_gas_limit vi gas_limit in
      let total_gas_used :=
        Alpha_context.Gas.Arith.add
          batch_state_value.(batch_state.total_gas_used)
          (Alpha_context.Gas.Arith.fp_value gas_limit) in
      let? '_ :=
        may_trace_gas_limit_too_high vi
          (Error_monad.error_unless
            (Alpha_context.Gas.Arith.op_lteq
              (Alpha_context.Gas.Arith.fp_value total_gas_used)
              remaining_block_gas)
            (Build_extensible "Block_quota_exceeded" unit tt)) in
      let? remaining_gas :=
        Error_monad.record_trace
          (Build_extensible "Insufficient_gas_for_manager" unit tt)
          (Alpha_context.Gas.consume_from
            (Alpha_context.Gas.Arith.fp_value gas_limit)
            Michelson_v1_gas.Cost_of.manager_operation) in
      let? '_ := check_storage_limit vi storage_limit in
      let? '_ :=
        Error_monad.error_unless batch_state_value.(batch_state.is_allocated)
          (Build_extensible "Empty_implicit_contract"
            Alpha_context.public_key_hash source) in
      let? '_ :=
        match operation with
        | Alpha_context.Reveal pk
          Alpha_context.Contract.check_public_key pk source
        |
          Alpha_context.Transaction {|
            Alpha_context.manager_operation.Transaction.parameters := parameters
              |} ⇒
          let? '_ := consume_decoding_gas remaining_gas parameters in
          Error_monad.Result_syntax.return_unit
        |
          Alpha_context.Origination {|
            Alpha_context.manager_operation.Origination.script := script |}
          ⇒
          let? remaining_gas :=
            consume_decoding_gas remaining_gas
              script.(Alpha_context.Script.t.code) in
          let? '_ :=
            consume_decoding_gas remaining_gas
              script.(Alpha_context.Script.t.storage) in
          Error_monad.Result_syntax.return_unit
        |
          Alpha_context.Register_global_constant {|
            Alpha_context.manager_operation.Register_global_constant.value := value_value
              |} ⇒
          let? '_ := consume_decoding_gas remaining_gas value_value in
          Error_monad.Result_syntax.return_unit
        |
          (Alpha_context.Delegation _ | Alpha_context.Set_deposits_limit _ |
          Alpha_context.Increase_paid_storage _ |
          Alpha_context.Update_consensus_key _) ⇒
          Error_monad.Result_syntax.return_unit
        | Alpha_context.Tx_rollup_origination
          assert_tx_rollup_feature_enabled vi
        |
          Alpha_context.Tx_rollup_submit_batch {|
            Alpha_context.manager_operation.Tx_rollup_submit_batch.content := content
              |} ⇒ validate_tx_rollup_submit_batch vi remaining_gas content
        |
          (Alpha_context.Tx_rollup_commit _ |
          Alpha_context.Tx_rollup_return_bond _ |
          Alpha_context.Tx_rollup_finalize_commitment _ |
          Alpha_context.Tx_rollup_remove_commitment _) ⇒
          assert_tx_rollup_feature_enabled vi
        |
          Alpha_context.Transfer_ticket {|
            Alpha_context.manager_operation.Transfer_ticket.contents := contents;
              Alpha_context.manager_operation.Transfer_ticket.ty := ty_value
              |} ⇒
          let? '_ := assert_tx_rollup_feature_enabled vi in
          let? remaining_gas := consume_decoding_gas remaining_gas contents in
          let? '_ := consume_decoding_gas remaining_gas ty_value in
          Error_monad.Result_syntax.return_unit
        | Alpha_context.Tx_rollup_dispatch_tickets _
          validate_tx_rollup_dispatch_tickets vi remaining_gas operation
        | Alpha_context.Tx_rollup_rejection _
          validate_tx_rollup_rejection vi operation
        |
          (Alpha_context.Sc_rollup_originate _ |
          Alpha_context.Sc_rollup_cement _ | Alpha_context.Sc_rollup_publish _ |
          Alpha_context.Sc_rollup_refute _ | Alpha_context.Sc_rollup_timeout _ |
          Alpha_context.Sc_rollup_execute_outbox_message _) ⇒
          assert_sc_rollup_feature_enabled vi
        |
          Alpha_context.Sc_rollup_add_messages {|
            Alpha_context.manager_operation.Sc_rollup_add_messages.messages := messages
              |} ⇒
          let? '_ := assert_sc_rollup_feature_enabled vi in
          assert_not_zero_messages messages
        | Alpha_context.Sc_rollup_recover_bond _
          assert_sc_rollup_feature_enabled vi
        |
          Alpha_context.Dal_publish_slot_header {|
            Alpha_context.manager_operation.Dal_publish_slot_header.slot_header :=
              slot_header
              |} ⇒
          Dal_apply.validate_publish_slot_header vi.(info.ctxt) slot_header
        |
          (Alpha_context.Zk_rollup_origination _ |
          Alpha_context.Zk_rollup_publish _ | Alpha_context.Zk_rollup_update _)
          ⇒ assert_zk_rollup_feature_enabled vi
        end in
      let? '(balance, is_allocated) :=
        Alpha_context.Contract.simulate_spending vi.(info.ctxt)
          batch_state_value.(batch_state.balance) fee source in
      return?
        {| batch_state.balance := balance;
          batch_state.is_allocated := is_allocated;
          batch_state.total_gas_used := total_gas_used; |}
    | _unreachable_gadt_branch
    end.

This would be [fold_left_es (check_contents vi) batch_state contents_list] if [contents_list] were an ordinary [list].
  Fixpoint check_contents_list
    (vi : info) (batch_state_value : batch_state)
    (contents_list : Alpha_context.contents_list)
    (remaining_gas : Alpha_context.Gas.Arith.fp)
    : M? Alpha_context.Gas.Arith.fp :=
    match contents_list with
    | Alpha_context.Single contents
      let? batch_state_value :=
        check_contents vi batch_state_value contents remaining_gas in
      return? batch_state_value.(batch_state.total_gas_used)
    | Alpha_context.Cons contents tail
      let? batch_state_value :=
        check_contents vi batch_state_value contents remaining_gas in
      check_contents_list vi batch_state_value tail remaining_gas
    end.

  Definition check_manager_operation
    (vi : info) (check_signature : bool) (operation : Alpha_context.operation)
    (remaining_block_gas : Alpha_context.Gas.Arith.fp)
    : M? Alpha_context.Gas.Arith.fp :=
    let contents_list :=
      operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
      in
    let? '(batch_state_value, source_pk) :=
      check_sanity_and_find_public_key vi contents_list in
    let? gas_used :=
      check_contents_list vi batch_state_value contents_list remaining_block_gas
      in
    let? '_ :=
      if check_signature then
        Alpha_context.Operation.check_signature source_pk vi.(info.chain_id)
          operation
      else
        ok_unit in
    return? gas_used.

  Definition check_manager_operation_conflict
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict :=
    let source :=
      match
        operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
        with
      |
        (Alpha_context.Single
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source |}) |
        Alpha_context.Cons
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source |}) _)
        ⇒ source
      | _unreachable_gadt_branch
      end in
    match
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.find_opt)
        source
        vs.(operation_conflict_state.manager_state).(manager_state.managers_seen)
      with
    | Noneok_unit
    | Some existing
      Pervasives.Error
        (Validate_errors.Operation_conflict
          {|
            Validate_errors.operation_conflict.Operation_conflict.existing :=
              existing;
            Validate_errors.operation_conflict.Operation_conflict.new_operation
              := oph; |})
    end.

  Definition wrap_check_manager_operation_conflict
    (operation : Alpha_context.operation)
    : Pervasives.result unit Validate_errors.operation_conflict M? unit :=
    let source :=
      match
        operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
        with
      |
        (Alpha_context.Single
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source |}) |
        Alpha_context.Cons
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source |}) _)
        ⇒ source
      | _unreachable_gadt_branch
      end in
    fun (function_parameter :
      Pervasives.result unit Validate_errors.operation_conflict) ⇒
      match function_parameter with
      | Pervasives.Ok _ok_unit
      | Pervasives.Error conflict
        Error_monad.error_value
          (Build_extensible "Manager_restriction"
            Validate_errors.Manager.Manager_restriction
            {| Validate_errors.Manager.Manager_restriction.source := source;
              Validate_errors.Manager.Manager_restriction.conflict := conflict;
              |})
      end.

  Definition add_manager_operation
    (vs : operation_conflict_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : operation_conflict_state :=
    let source :=
      match
        operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
        with
      |
        (Alpha_context.Single
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source |}) |
        Alpha_context.Cons
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source |}) _)
        ⇒ source
      | _unreachable_gadt_branch
      end in
    let managers_seen :=
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.add)
        source oph
        vs.(operation_conflict_state.manager_state).(manager_state.managers_seen)
      in
    operation_conflict_state.with_manager_state
      {| manager_state.managers_seen := managers_seen; |} vs.

  Definition may_update_remaining_gas_used
    (mode : mode) (block_state_value : block_state)
    (operation_gas_used : Alpha_context.Gas.Arith.t) : block_state :=
    match mode with
    | (Application _ | Partial_validation _ | Construction _) ⇒
      let remaining_block_gas :=
        Alpha_context.Gas.Arith.sub
          block_state_value.(block_state.remaining_block_gas) operation_gas_used
        in
      block_state.with_remaining_block_gas remaining_block_gas block_state_value
    | Mempoolblock_state_value
    end.

  Definition remove_manager_operation
    (vs : operation_conflict_state) (operation : Alpha_context.operation)
    : operation_conflict_state :=
    let source :=
      match
        operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
        with
      |
        (Alpha_context.Single
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source |}) |
        Alpha_context.Cons
          (Alpha_context.Manager_operation {|
            Alpha_context.contents.Manager_operation.source := source |}) _)
        ⇒ source
      | _unreachable_gadt_branch
      end in
    let managers_seen :=
      Signature.Public_key_hash.(S.SIGNATURE_PUBLIC_KEY_HASH.Map).(S.INDEXES_MAP.remove)
        source
        vs.(operation_conflict_state.manager_state).(manager_state.managers_seen)
      in
    operation_conflict_state.with_manager_state
      {| manager_state.managers_seen := managers_seen; |} vs.

  Definition validate_manager_operation
    (check_signature : bool) (info_value : info)
    (operation_state : operation_conflict_state)
    (block_state_value : block_state) (oph : Operation_hash.t)
    (operation : Alpha_context.operation) : M? validation_state :=
    let? gas_used :=
      check_manager_operation info_value check_signature operation
        block_state_value.(block_state.remaining_block_gas) in
    let? '_ :=
      wrap_check_manager_operation_conflict operation
        (check_manager_operation_conflict operation_state oph operation) in
    let operation_state := add_manager_operation operation_state oph operation
      in
    let block_state_value :=
      may_update_remaining_gas_used info_value.(info.mode) block_state_value
        gas_used in
    return?
      {| validation_state.info := info_value;
        validation_state.operation_state := operation_state;
        validation_state.block_state := block_state_value; |}.
End Manager.

Definition init_validation_state
  (ctxt : Alpha_context.t) (mode : mode) (chain_id : Chain_id.t)
  (all_expected_consensus_features : all_expected_consensus_features)
  (predecessor_level : Alpha_context.Raw_level.t) : validation_state :=
  let info_value :=
    init_info_aux ctxt mode chain_id all_expected_consensus_features in
  let operation_state := init_operation_conflict_state predecessor_level in
  let block_state_value := init_block_state info_value in
  {| validation_state.info := info_value;
    validation_state.operation_state := operation_state;
    validation_state.block_state := block_state_value; |}.

Definition begin_any_application
  (ctxt : Alpha_context.context) (chain_id : Chain_id.t)
  (predecessor_level : Alpha_context.Level.t) (predecessor_timestamp : Time.t)
  (block_header : Alpha_context.Block_header.t)
  (fitness : Alpha_context.Fitness.t) (is_partial : bool)
  : M? validation_state :=
  let predecessor_round := Alpha_context.Fitness.predecessor_round fitness in
  let round := Alpha_context.Fitness.round fitness in
  let current_level := Alpha_context.Level.current ctxt in
  let? '(ctxt, _slot, block_producer) :=
    Alpha_context.Stake_distribution.baking_rights_owner ctxt current_level
      round in
  let? '_ :=
    Alpha_context.Block_header.begin_validate_block_header block_header chain_id
      predecessor_timestamp predecessor_round fitness
      block_header.(Alpha_context.Block_header.t.shell).(Block_header.shell_header.timestamp)
      block_producer.(Raw_context.consensus_pk.consensus_pk)
      (Alpha_context.Constants.round_durations ctxt)
      (Alpha_context.Constants.proof_of_work_threshold ctxt)
      current_level.(Alpha_context.Level.t.expected_commitment) in
  let? '_ :=
    Consensus.check_frozen_deposits_are_positive ctxt
      block_producer.(Raw_context.consensus_pk.delegate) in
  let? '(ctxt, _slot, payload_producer) :=
    Alpha_context.Stake_distribution.baking_rights_owner ctxt current_level
      block_header.(Alpha_context.Block_header.t.protocol_data).(Alpha_context.Block_header.protocol_data.contents).(Alpha_context.Block_header.contents.payload_round)
    in
  let payload_hash :=
    block_header.(Alpha_context.Block_header.t.protocol_data).(Alpha_context.Block_header.protocol_data.contents).(Alpha_context.Block_header.contents.payload_hash)
    in
  let predecessor_hash :=
    block_header.(Alpha_context.Block_header.t.shell).(Block_header.shell_header.predecessor)
    in
  let block_finalization_info :=
    {| block_finalization_info.fitness := fitness;
      block_finalization_info.block_producer := block_producer;
      block_finalization_info.payload_producer := payload_producer;
      block_finalization_info.predecessor_hash := predecessor_hash;
      block_finalization_info.block_data_contents :=
        block_header.(Alpha_context.Block_header.t.protocol_data).(Alpha_context.Block_header.protocol_data.contents);
      |} in
  let mode :=
    if is_partial then
      Partial_validation block_finalization_info
    else
      Application block_finalization_info in
  let all_expected_consensus_features :=
    Consensus.expected_features_for_application ctxt fitness payload_hash
      predecessor_level predecessor_round predecessor_hash in
  let predecessor_level := predecessor_level.(Alpha_context.Level.t.level) in
  return?
    (init_validation_state ctxt mode chain_id all_expected_consensus_features
      predecessor_level).

Definition begin_partial_validation
  (ctxt : Alpha_context.context) (chain_id : Chain_id.t)
  (predecessor_level : Alpha_context.Level.t) (predecessor_timestamp : Time.t)
  (block_header : Alpha_context.Block_header.t)
  (fitness : Alpha_context.Fitness.t) : M? validation_state :=
  begin_any_application ctxt chain_id predecessor_level predecessor_timestamp
    block_header fitness true.

Definition begin_application
  (ctxt : Alpha_context.context) (chain_id : Chain_id.t)
  (predecessor_level : Alpha_context.Level.t) (predecessor_timestamp : Time.t)
  (block_header : Alpha_context.Block_header.t)
  (fitness : Alpha_context.Fitness.t) : M? validation_state :=
  begin_any_application ctxt chain_id predecessor_level predecessor_timestamp
    block_header fitness false.

Definition begin_full_construction
  (ctxt : Alpha_context.context) (chain_id : Chain_id.t)
  (predecessor_level : Alpha_context.Level.t)
  (predecessor_round : Alpha_context.Round.t) (predecessor_timestamp : Time.t)
  (predecessor_hash : Block_hash.t) (round : Alpha_context.Round.t)
  (header_contents : Alpha_context.Block_header.contents)
  : M? validation_state :=
  let round_durations := Alpha_context.Constants.round_durations ctxt in
  let timestamp := Alpha_context.Timestamp.current ctxt in
  let? '_ :=
    Alpha_context.Block_header.check_timestamp round_durations timestamp round
      predecessor_timestamp predecessor_round in
  let current_level := Alpha_context.Level.current ctxt in
  let? '(ctxt, _slot, block_producer) :=
    Alpha_context.Stake_distribution.baking_rights_owner ctxt current_level
      round in
  let? '_ :=
    Consensus.check_frozen_deposits_are_positive ctxt
      block_producer.(Raw_context.consensus_pk.delegate) in
  let? '(ctxt, _slot, payload_producer) :=
    Alpha_context.Stake_distribution.baking_rights_owner ctxt current_level
      header_contents.(Alpha_context.Block_header.contents.payload_round) in
  let all_expected_consensus_features :=
    Consensus.expected_features_for_construction ctxt round
      header_contents.(Alpha_context.Block_header.contents.payload_hash)
      predecessor_level predecessor_round predecessor_hash in
  let predecessor_level := predecessor_level.(Alpha_context.Level.t.level) in
  let validation_state :=
    init_validation_state ctxt
      (Construction
        {| mode.Construction.predecessor_round := predecessor_round;
          mode.Construction.predecessor_hash := predecessor_hash;
          mode.Construction.round := round;
          mode.Construction.block_data_contents := header_contents;
          mode.Construction.block_producer := block_producer;
          mode.Construction.payload_producer := payload_producer; |}) chain_id
      all_expected_consensus_features predecessor_level in
  return? validation_state.

Definition begin_partial_construction
  (ctxt : Alpha_context.t) (chain_id : Chain_id.t)
  (predecessor_level : Alpha_context.Level.t)
  (predecessor_round : Alpha_context.Round.t)
  (grandparent_round : Alpha_context.Round.t) : validation_state :=
  let all_expected_consensus_features :=
    Consensus.expected_features_for_partial_construction ctxt predecessor_level
      predecessor_round grandparent_round in
  let predecessor_level := predecessor_level.(Alpha_context.Level.t.level) in
  let validation_state :=
    init_validation_state ctxt Mempool chain_id all_expected_consensus_features
      predecessor_level in
  validation_state.

Definition begin_no_predecessor_info
  (ctxt : Alpha_context.context) (chain_id : Chain_id.t) : validation_state :=
  let all_expected_consensus_features :=
    {|
      all_expected_consensus_features.expected_preendorsement :=
        No_predecessor_info_cannot_validate_preendorsement;
      all_expected_consensus_features.expected_endorsement :=
        No_predecessor_info_cannot_validate_endorsement;
      all_expected_consensus_features.expected_grandparent_endorsement_for_partial_construction
        := None; |} in
  let current_level := Alpha_context.Level.current ctxt in
  let predecessor_level :=
    match
      Alpha_context.Raw_level.pred current_level.(Alpha_context.Level.t.level)
      with
    | Nonecurrent_level.(Alpha_context.Level.t.level)
    | Some levellevel
    end in
  init_validation_state ctxt Mempool chain_id all_expected_consensus_features
    predecessor_level.

Definition check_operation (op_staroptstar : option bool)
  : info Alpha_context.operation M? unit :=
  let check_signature :=
    match op_staroptstar with
    | Some op_starsthstarop_starsthstar
    | Nonetrue
    end in
  fun (info_value : info) ⇒
    fun (operation : Alpha_context.operation) ⇒
      match
        operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
        with
      | Alpha_context.Single (Alpha_context.Preendorsement _) ⇒
        let? '_voting_power :=
          Consensus.check_preendorsement info_value check_signature operation in
        Error_monad.Lwt_result_syntax.return_unit
      | Alpha_context.Single (Alpha_context.Endorsement _) ⇒
        let? '_kind :=
          Consensus.check_endorsement info_value check_signature operation in
        Error_monad.Lwt_result_syntax.return_unit
      | Alpha_context.Single (Alpha_context.Dal_attestation _) ⇒
        Consensus.check_dal_attestation info_value operation
      | Alpha_context.Single (Alpha_context.Proposals _) ⇒
        Voting.check_proposals info_value check_signature operation
      | Alpha_context.Single (Alpha_context.Ballot _) ⇒
        Voting.check_ballot info_value check_signature operation
      | Alpha_context.Single (Alpha_context.Activate_account _) ⇒
        Anonymous.check_activate_account info_value operation
      | Alpha_context.Single (Alpha_context.Double_preendorsement_evidence _) ⇒
        Anonymous.check_double_preendorsement_evidence info_value operation
      | Alpha_context.Single (Alpha_context.Double_endorsement_evidence _) ⇒
        Anonymous.check_double_endorsement_evidence info_value operation
      | Alpha_context.Single (Alpha_context.Double_baking_evidence _) ⇒
        Anonymous.check_double_baking_evidence info_value operation
      | Alpha_context.Single (Alpha_context.Drain_delegate _) ⇒
        Anonymous.check_drain_delegate info_value check_signature operation
      | Alpha_context.Single (Alpha_context.Seed_nonce_revelation _) ⇒
        Anonymous.check_seed_nonce_revelation info_value operation
      | Alpha_context.Single (Alpha_context.Vdf_revelation _) ⇒
        Anonymous.check_vdf_revelation info_value operation
      | Alpha_context.Single (Alpha_context.Manager_operation _) ⇒
        let remaining_gas :=
          Alpha_context.Gas.Arith.fp_value
            (Alpha_context.Constants.hard_gas_limit_per_block
              info_value.(info.ctxt)) in
        let? '_remaining_gas :=
          Manager.check_manager_operation info_value check_signature operation
            remaining_gas in
        Error_monad.Lwt_result_syntax.return_unit
      | Alpha_context.Cons (Alpha_context.Manager_operation _) _
        let remaining_gas :=
          Alpha_context.Gas.Arith.fp_value
            (Alpha_context.Constants.hard_gas_limit_per_block
              info_value.(info.ctxt)) in
        let? '_remaining_gas :=
          Manager.check_manager_operation info_value check_signature operation
            remaining_gas in
        Error_monad.Lwt_result_syntax.return_unit
      | Alpha_context.Single (Alpha_context.Failing_noop _) ⇒
        Error_monad.Lwt_result_syntax.tzfail
          (Build_extensible "Failing_noop_error" unit tt)
      | _unreachable_gadt_branch
      end.

Definition check_operation_conflict
  (operation_conflict_state_value : operation_conflict_state)
  (oph : Operation_hash.t) (operation : Alpha_context.operation)
  : Pervasives.result unit Validate_errors.operation_conflict :=
  match
    operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
    with
  | Alpha_context.Single (Alpha_context.Preendorsement _) ⇒
    Consensus.check_preendorsement_conflict operation_conflict_state_value oph
      operation
  | Alpha_context.Single (Alpha_context.Endorsement _) ⇒
    Consensus.check_endorsement_conflict operation_conflict_state_value oph
      operation
  | Alpha_context.Single (Alpha_context.Dal_attestation _) ⇒
    Consensus.check_dal_attestation_conflict operation_conflict_state_value oph
      operation
  | Alpha_context.Single (Alpha_context.Proposals _) ⇒
    Voting.check_proposals_conflict operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Ballot _) ⇒
    Voting.check_ballot_conflict operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Activate_account _) ⇒
    Anonymous.check_activate_account_conflict operation_conflict_state_value oph
      operation
  | Alpha_context.Single (Alpha_context.Double_preendorsement_evidence _) ⇒
    Anonymous.check_double_preendorsement_evidence_conflict
      operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Double_endorsement_evidence _) ⇒
    Anonymous.check_double_endorsement_evidence_conflict
      operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Double_baking_evidence _) ⇒
    Anonymous.check_double_baking_evidence_conflict
      operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Drain_delegate _) ⇒
    Anonymous.check_drain_delegate_conflict operation_conflict_state_value oph
      operation
  | Alpha_context.Single (Alpha_context.Seed_nonce_revelation _) ⇒
    Anonymous.check_seed_nonce_revelation_conflict
      operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Vdf_revelation _) ⇒
    Anonymous.check_vdf_revelation_conflict operation_conflict_state_value oph
  | Alpha_context.Single (Alpha_context.Manager_operation _) ⇒
    Manager.check_manager_operation_conflict operation_conflict_state_value oph
      operation
  | Alpha_context.Cons (Alpha_context.Manager_operation _) _
    Manager.check_manager_operation_conflict operation_conflict_state_value oph
      operation
  | Alpha_context.Single (Alpha_context.Failing_noop _) ⇒ ok_unit
  | _unreachable_gadt_branch
  end.

Definition add_valid_operation
  (operation_conflict_state_value : operation_conflict_state)
  (oph : Operation_hash.t) (operation : Alpha_context.operation)
  : operation_conflict_state :=
  match
    operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
    with
  | Alpha_context.Single (Alpha_context.Preendorsement _) ⇒
    Consensus.add_preendorsement operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Endorsement consensus_content) ⇒
    let endorsement_kind :=
      if
        Consensus.is_normal_endorsement_assuming_valid
          operation_conflict_state_value consensus_content
      then
        Consensus.Normal_endorsement 0
      else
        Consensus.Grandparent_endorsement in
    Consensus.add_endorsement operation_conflict_state_value oph operation
      endorsement_kind
  | Alpha_context.Single (Alpha_context.Dal_attestation _) ⇒
    Consensus.add_dal_attestation operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Proposals _) ⇒
    Voting.add_proposals operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Ballot _) ⇒
    Voting.add_ballot operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Activate_account _) ⇒
    Anonymous.add_activate_account operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Double_preendorsement_evidence _) ⇒
    Anonymous.add_double_preendorsement_evidence operation_conflict_state_value
      oph operation
  | Alpha_context.Single (Alpha_context.Double_endorsement_evidence _) ⇒
    Anonymous.add_double_endorsement_evidence operation_conflict_state_value oph
      operation
  | Alpha_context.Single (Alpha_context.Double_baking_evidence _) ⇒
    Anonymous.add_double_baking_evidence operation_conflict_state_value oph
      operation
  | Alpha_context.Single (Alpha_context.Drain_delegate _) ⇒
    Anonymous.add_drain_delegate operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Seed_nonce_revelation _) ⇒
    Anonymous.add_seed_nonce_revelation operation_conflict_state_value oph
      operation
  | Alpha_context.Single (Alpha_context.Vdf_revelation _) ⇒
    Anonymous.add_vdf_revelation operation_conflict_state_value oph
  | Alpha_context.Single (Alpha_context.Manager_operation _) ⇒
    Manager.add_manager_operation operation_conflict_state_value oph operation
  | Alpha_context.Cons (Alpha_context.Manager_operation _) _
    Manager.add_manager_operation operation_conflict_state_value oph operation
  | Alpha_context.Single (Alpha_context.Failing_noop _) ⇒
    operation_conflict_state_value
  | _unreachable_gadt_branch
  end.

Definition remove_operation
  (operation_conflict_state_value : operation_conflict_state)
  (operation : Alpha_context.operation) : operation_conflict_state :=
  match
    operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
    with
  | Alpha_context.Single (Alpha_context.Preendorsement _) ⇒
    Consensus.remove_preendorsement operation_conflict_state_value operation
  | Alpha_context.Single (Alpha_context.Endorsement _) ⇒
    Consensus.remove_endorsement operation_conflict_state_value operation
  | Alpha_context.Single (Alpha_context.Dal_attestation _) ⇒
    Consensus.remove_dal_attestation operation_conflict_state_value operation
  | Alpha_context.Single (Alpha_context.Proposals _) ⇒
    Voting.remove_proposals operation_conflict_state_value operation
  | Alpha_context.Single (Alpha_context.Ballot _) ⇒
    Voting.remove_ballot operation_conflict_state_value operation
  | Alpha_context.Single (Alpha_context.Activate_account _) ⇒
    Anonymous.remove_activate_account operation_conflict_state_value operation
  | Alpha_context.Single (Alpha_context.Double_preendorsement_evidence _) ⇒
    Anonymous.remove_double_preendorsement_evidence
      operation_conflict_state_value operation
  | Alpha_context.Single (Alpha_context.Double_endorsement_evidence _) ⇒
    Anonymous.remove_double_endorsement_evidence operation_conflict_state_value
      operation
  | Alpha_context.Single (Alpha_context.Double_baking_evidence _) ⇒
    Anonymous.remove_double_baking_evidence operation_conflict_state_value
      operation
  | Alpha_context.Single (Alpha_context.Drain_delegate _) ⇒
    Anonymous.remove_drain_delegate operation_conflict_state_value operation
  | Alpha_context.Single (Alpha_context.Seed_nonce_revelation _) ⇒
    Anonymous.remove_seed_nonce_revelation operation_conflict_state_value
      operation
  | Alpha_context.Single (Alpha_context.Vdf_revelation _) ⇒
    Anonymous.remove_vdf_revelation operation_conflict_state_value
  | Alpha_context.Single (Alpha_context.Manager_operation _) ⇒
    Manager.remove_manager_operation operation_conflict_state_value operation
  | Alpha_context.Cons (Alpha_context.Manager_operation _) _
    Manager.remove_manager_operation operation_conflict_state_value operation
  | Alpha_context.Single (Alpha_context.Failing_noop _) ⇒
    operation_conflict_state_value
  | _unreachable_gadt_branch
  end.

Definition check_validation_pass_consistency
  (vi : info) (vs : block_state) (validation_pass : option int)
  : M? block_state :=
  match vi.(info.mode) with
  | (Mempool | Construction _) ⇒ return? vs
  | (Application _ | Partial_validation _) ⇒
    match (vs.(block_state.last_op_validation_pass), validation_pass) with
    | (None, validation_pass)
      return? (block_state.with_last_op_validation_pass validation_pass vs)
    | (Some previous_vp, Some validation_pass)
      let? '_ :=
        Error_monad.fail_unless (previous_vp i validation_pass)
          (Build_extensible "Inconsistent_validation_passes_in_block"
            Validate_errors.Block.Inconsistent_validation_passes_in_block
            {|
              Validate_errors.Block.Inconsistent_validation_passes_in_block.expected
                := previous_vp;
              Validate_errors.Block.Inconsistent_validation_passes_in_block.provided
                := validation_pass; |}) in
      return?
        (block_state.with_last_op_validation_pass (Some validation_pass) vs)
    | (Some _, None)
      Error_monad.Lwt_result_syntax.tzfail
        (Build_extensible "Failing_noop_error" unit tt)
    end
  end.

Increment [vs.op_count] for all operations, and record non-consensus operation hashes in [vs.recorded_operations_rev].
Definition record_operation
  (vs : block_state) (ophash : Operation_hash.t)
  (validation_pass_opt : option int) : block_state :=
  let op_count := vs.(block_state.op_count) +i 1 in
  match
    (validation_pass_opt,
      match validation_pass_opt with
      | Some n_valuen_value =i Operation_repr.consensus_pass
      | _false
      end) with
  | (Some n_value, true)block_state.with_op_count op_count vs
  | (_, _)
    block_state.with_recorded_operations_rev
      (cons ophash vs.(block_state.recorded_operations_rev))
      (block_state.with_op_count op_count vs)
  end.

Definition validate_operation (op_staroptstar : option bool)
  : validation_state Operation_hash.t Alpha_context.packed_operation
  M? validation_state :=
  let check_signature :=
    match op_staroptstar with
    | Some op_starsthstarop_starsthstar
    | Nonetrue
    end in
  fun (function_parameter : validation_state) ⇒
    let '{|
      validation_state.info := info_value;
        validation_state.operation_state := operation_state;
        validation_state.block_state := block_state_value
        |} := function_parameter in
    fun (oph : Operation_hash.t) ⇒
      fun (packed_operation : Alpha_context.packed_operation) ⇒
        let '{|
          Alpha_context.packed_operation.shell := shell;
            Alpha_context.packed_operation.protocol_data :=
              Alpha_context.Operation_data protocol_data
            |} := packed_operation in
        let validation_pass_opt :=
          Alpha_context.Operation.acceptable_pass packed_operation in
        let? block_state_value :=
          check_validation_pass_consistency info_value block_state_value
            validation_pass_opt in
        let block_state_value :=
          record_operation block_state_value oph validation_pass_opt in
        let operation :=
          {| Alpha_context.operation.shell := shell;
            Alpha_context.operation.protocol_data := protocol_data; |} in
        match
          ((info_value.(info.mode), validation_pass_opt),
            match (info_value.(info.mode), validation_pass_opt) with
            | (Partial_validation _, Some n_value)
              n_value i Operation_repr.consensus_pass
            | _false
            end) with
        | ((Partial_validation _, Some n_value), true)
          return?
            {| validation_state.info := info_value;
              validation_state.operation_state := operation_state;
              validation_state.block_state := block_state_value; |}
        |
          (((Partial_validation _, _) | (Mempool, _) | (Construction _, _) |
          (Application _, _)), _)
          match
            operation.(Alpha_context.operation.protocol_data).(Alpha_context.protocol_data.contents)
            with
          | Alpha_context.Single (Alpha_context.Preendorsement _) ⇒
            Consensus.validate_preendorsement check_signature info_value
              operation_state block_state_value oph operation
          | Alpha_context.Single (Alpha_context.Endorsement _) ⇒
            Consensus.validate_endorsement check_signature info_value
              operation_state block_state_value oph operation
          | Alpha_context.Single (Alpha_context.Dal_attestation _) ⇒
            let? '_ := Consensus.check_dal_attestation info_value operation in
            let? '_ :=
              Consensus.wrap_dal_attestation_conflict
                (Consensus.check_dal_attestation_conflict operation_state oph
                  operation) in
            let operation_state :=
              Consensus.add_dal_attestation operation_state oph operation in
            return?
              {| validation_state.info := info_value;
                validation_state.operation_state := operation_state;
                validation_state.block_state := block_state_value; |}
          | Alpha_context.Single (Alpha_context.Proposals _) ⇒
            let? '_ :=
              Voting.check_proposals info_value check_signature operation in
            let? '_ :=
              Voting.wrap_proposals_conflict
                (Voting.check_proposals_conflict operation_state oph operation)
              in
            let operation_state :=
              Voting.add_proposals operation_state oph operation in
            return?
              {| validation_state.info := info_value;
                validation_state.operation_state := operation_state;
                validation_state.block_state := block_state_value; |}
          | Alpha_context.Single (Alpha_context.Ballot _) ⇒
            let? '_ := Voting.check_ballot info_value check_signature operation
              in
            let? '_ :=
              Voting.wrap_ballot_conflict
                (Voting.check_ballot_conflict operation_state oph operation) in
            let operation_state :=
              Voting.add_ballot operation_state oph operation in
            return?
              {| validation_state.info := info_value;
                validation_state.operation_state := operation_state;
                validation_state.block_state := block_state_value; |}
          | Alpha_context.Single (Alpha_context.Activate_account _) ⇒
            let? '_ := Anonymous.check_activate_account info_value operation in
            let? '_ :=
              Anonymous.wrap_activate_account_conflict operation
                (Anonymous.check_activate_account_conflict operation_state oph
                  operation) in
            let operation_state :=
              Anonymous.add_activate_account operation_state oph operation in
            return?
              {| validation_state.info := info_value;
                validation_state.operation_state := operation_state;
                validation_state.block_state := block_state_value; |}
          |
            Alpha_context.Single
              (Alpha_context.Double_preendorsement_evidence _) ⇒
            let? '_ :=
              Anonymous.check_double_preendorsement_evidence info_value
                operation in
            let? '_ :=
              Anonymous.wrap_denunciation_conflict
                Validate_errors.Anonymous.Preendorsement
                (Anonymous.check_double_preendorsement_evidence_conflict
                  operation_state oph operation) in
            let operation_state :=
              Anonymous.add_double_preendorsement_evidence operation_state oph
                operation in
            return?
              {| validation_state.info := info_value;
                validation_state.operation_state := operation_state;
                validation_state.block_state := block_state_value; |}
          | Alpha_context.Single (Alpha_context.Double_endorsement_evidence _)
            ⇒
            let? '_ :=
              Anonymous.check_double_endorsement_evidence info_value operation
              in
            let? '_ :=
              Anonymous.wrap_denunciation_conflict
                Validate_errors.Anonymous.Endorsement
                (Anonymous.check_double_endorsement_evidence_conflict
                  operation_state oph operation) in
            let operation_state :=
              Anonymous.add_double_endorsement_evidence operation_state oph
                operation in
            return?
              {| validation_state.info := info_value;
                validation_state.operation_state := operation_state;
                validation_state.block_state := block_state_value; |}
          | Alpha_context.Single (Alpha_context.Double_baking_evidence _) ⇒
            let? '_ :=
              Anonymous.check_double_baking_evidence info_value operation in
            let? '_ :=
              Anonymous.wrap_denunciation_conflict
                Validate_errors.Anonymous.Block
                (Anonymous.check_double_baking_evidence_conflict operation_state
                  oph operation) in
            let operation_state :=
              Anonymous.add_double_baking_evidence operation_state oph operation
              in
            return?
              {| validation_state.info := info_value;
                validation_state.operation_state := operation_state;
                validation_state.block_state := block_state_value; |}
          | Alpha_context.Single (Alpha_context.Drain_delegate _) ⇒
            let? '_ :=
              Anonymous.check_drain_delegate info_value check_signature
                operation in
            let? '_ :=
              Anonymous.wrap_drain_delegate_conflict operation
                (Anonymous.check_drain_delegate_conflict operation_state oph
                  operation) in
            let operation_state :=
              Anonymous.add_drain_delegate operation_state oph operation in
            return?
              {| validation_state.info := info_value;
                validation_state.operation_state := operation_state;
                validation_state.block_state := block_state_value; |}
          | Alpha_context.Single (Alpha_context.Seed_nonce_revelation _) ⇒
            let? '_ :=
              Anonymous.check_seed_nonce_revelation info_value operation in
            let? '_ :=
              Anonymous.wrap_seed_nonce_revelation_conflict
                (Anonymous.check_seed_nonce_revelation_conflict operation_state
                  oph operation) in
            let operation_state :=
              Anonymous.add_seed_nonce_revelation operation_state oph operation
              in
            return?
              {| validation_state.info := info_value;
                validation_state.operation_state := operation_state;
                validation_state.block_state := block_state_value; |}
          | Alpha_context.Single (Alpha_context.Vdf_revelation _) ⇒
            let? '_ := Anonymous.check_vdf_revelation info_value operation in
            let? '_ :=
              Anonymous.wrap_vdf_revelation_conflict
                (Anonymous.check_vdf_revelation_conflict operation_state oph) in
            let operation_state :=
              Anonymous.add_vdf_revelation operation_state oph in
            return?
              {| validation_state.info := info_value;
                validation_state.operation_state := operation_state;
                validation_state.block_state := block_state_value; |}
          | Alpha_context.Single (Alpha_context.Manager_operation _) ⇒
            Manager.validate_manager_operation check_signature info_value
              operation_state block_state_value oph operation
          | Alpha_context.Cons (Alpha_context.Manager_operation _) _
            Manager.validate_manager_operation check_signature info_value
              operation_state block_state_value oph operation
          | Alpha_context.Single (Alpha_context.Failing_noop _) ⇒
            Error_monad.Lwt_result_syntax.tzfail
              (Build_extensible "Failing_noop_error" unit tt)
          | _unreachable_gadt_branch
          end
        end.

Definition are_endorsements_required (vi : info) : M? bool :=
  Error_monad.Lwt_result_syntax.op_letplus
    (Alpha_context.First_level_of_protocol.get vi.(info.ctxt))
    (fun first_level
      let level_position_in_protocol :=
        Alpha_context.Raw_level.diff_value
          vi.(info.current_level).(Alpha_context.Level.t.level) first_level in
      level_position_in_protocol >i32 1).

Definition check_endorsement_power (vi : info) (bs : block_state) : M? unit :=
  let required := Alpha_context.Constants.consensus_threshold vi.(info.ctxt) in
  let provided := bs.(block_state.endorsement_power) in
  Error_monad.error_unless (provided i required)
    (Build_extensible "Not_enough_endorsements"
      Validate_errors.Block.Not_enough_endorsements
      {| Validate_errors.Block.Not_enough_endorsements.required := required;
        Validate_errors.Block.Not_enough_endorsements.provided := provided; |}).

Definition finalize_validate_block_header
  (vi : info) (vs : block_state)
  (checkable_payload_hash : Alpha_context.Block_header.checkable_payload_hash)
  (block_header_contents : Alpha_context.Block_header.contents)
  (round : Alpha_context.Round.t) (fitness : Alpha_context.Fitness.t)
  : M? unit :=
  let locked_round_evidence :=
    Option.map
      (fun (function_parameter : Alpha_context.Round.t × int) ⇒
        let '(preendorsement_round, preendorsement_count) := function_parameter
          in
        {|
          Alpha_context.Block_header.locked_round_evidence.preendorsement_round
            := preendorsement_round;
          Alpha_context.Block_header.locked_round_evidence.preendorsement_count
            := preendorsement_count; |}) vs.(block_state.locked_round_evidence)
    in
  Alpha_context.Block_header.finalize_validate_block_header
    block_header_contents round fitness checkable_payload_hash
    locked_round_evidence
    (Alpha_context.Constants.consensus_threshold vi.(info.ctxt)).

Definition compute_payload_hash
  (block_state_value : block_state)
  (block_header_contents : Alpha_context.Block_header.contents)
  (predecessor_hash : Block_hash.t) : Block_payload_hash.t :=
  Alpha_context.Block_payload.hash_value predecessor_hash
    block_header_contents.(Alpha_context.Block_header.contents.payload_round)
    (List.rev block_state_value.(block_state.recorded_operations_rev)).

Definition finalize_block (function_parameter : validation_state) : M? unit :=
  let '{|
    validation_state.info := info_value;
      validation_state.block_state := block_state_value
      |} := function_parameter in
  match info_value.(info.mode) with
  |
    Application {|
      block_finalization_info.fitness := fitness;
        block_finalization_info.predecessor_hash := predecessor_hash;
        block_finalization_info.block_data_contents := block_data_contents
        |} ⇒
    let? are_endorsements_required := are_endorsements_required info_value in
    let? '_ :=
      if are_endorsements_required then
        check_endorsement_power info_value block_state_value
      else
        ok_unit in
    let block_payload_hash :=
      compute_payload_hash block_state_value block_data_contents
        predecessor_hash in
    let round := Alpha_context.Fitness.round fitness in
    let? '_ :=
      finalize_validate_block_header info_value block_state_value
        (Alpha_context.Block_header.Expected_payload_hash block_payload_hash)
        block_data_contents round fitness in
    Error_monad.Lwt_result_syntax.return_unit
  | Partial_validation _
    let? are_endorsements_required := are_endorsements_required info_value in
    let? '_ :=
      if are_endorsements_required then
        check_endorsement_power info_value block_state_value
      else
        ok_unit in
    Error_monad.Lwt_result_syntax.return_unit
  |
    Construction {|
      mode.Construction.predecessor_round := predecessor_round;
        mode.Construction.predecessor_hash := predecessor_hash;
        mode.Construction.round := round;
        mode.Construction.block_data_contents := block_data_contents
        |} ⇒
    let block_payload_hash :=
      compute_payload_hash block_state_value block_data_contents
        predecessor_hash in
    let locked_round_evidence :=
      block_state_value.(block_state.locked_round_evidence) in
    let checkable_payload_hash :=
      match locked_round_evidence with
      | Some _
        Alpha_context.Block_header.Expected_payload_hash block_payload_hash
      | NoneAlpha_context.Block_header.No_check
      end in
    let? are_endorsements_required := are_endorsements_required info_value in
    let? '_ :=
      if are_endorsements_required then
        check_endorsement_power info_value block_state_value
      else
        ok_unit in
    let? fitness :=
      let locked_round :=
        match locked_round_evidence with
        | NoneNone
        | Some (preendorsement_round, _power)Some preendorsement_round
        end in
      let level :=
        (Alpha_context.Level.current info_value.(info.ctxt)).(Alpha_context.Level.t.level)
        in
      let? fitness :=
        Alpha_context.Fitness.create level locked_round predecessor_round round
        in
      return? fitness in
    let? '_ :=
      finalize_validate_block_header info_value block_state_value
        checkable_payload_hash block_data_contents round fitness in
    Error_monad.Lwt_result_syntax.return_unit
  | MempoolError_monad.Lwt_result_syntax.return_unit
  end.