Skip to main content

🦏 Sc_rollup_proof_repr.v

Translated OCaml

See proofs, Gitlab , OCaml

File generated by coq-of-ocaml
Init function; without side-effects in Coq
Definition init_module_repr : unit :=
  let '_ :=
    Error_monad.register_error_kind Error_monad.Permanent
      "Sc_rollup_proof_check" "Invalid proof"
      "An invalid proof has been submitted"
      (Some
        (fun (fmt : Format.formatter) ⇒
          fun (msg : string) ⇒
            Format.fprintf fmt
              (CamlinternalFormatBasics.Format
                (CamlinternalFormatBasics.String_literal "Invalid proof: "
                  (CamlinternalFormatBasics.String
                    CamlinternalFormatBasics.No_padding
                    CamlinternalFormatBasics.End_of_format)) "Invalid proof: %s")
              msg))
      (Data_encoding.obj1
        (Data_encoding.req None None "reason" Data_encoding.string_value))
      (fun (function_parameter : Error_monad._error) ⇒
        match function_parameter with
        | Build_extensible tag _ payload
          if String.eqb tag "Sc_rollup_proof_check" then
            let msg := cast string payload in
            Some msg
          else None
        end)
      (fun (msg : string) ⇒ Build_extensible "Sc_rollup_proof_check" string msg)
    in
  Error_monad.register_error_kind Error_monad.Permanent
    "Sc_rollup_invalid_serialized_inbox_proof" "Invalid serialized inbox proof"
    "The serialized inbox proof can not be de-serialized"
    (Some
      (fun (fmt : Format.formatter) ⇒
        fun (function_parameter : unit) ⇒
          let '_ := function_parameter in
          Format.fprintf fmt
            (CamlinternalFormatBasics.Format
              (CamlinternalFormatBasics.String_literal
                "Invalid serialized inbox proof"
                CamlinternalFormatBasics.End_of_format)
              "Invalid serialized inbox proof"))) Data_encoding.unit_value
    (fun (function_parameter : Error_monad._error) ⇒
      match function_parameter with
      | Build_extensible tag _ payload
        if String.eqb tag "Sc_rollup_invalid_serialized_inbox_proof" then
          Some tt
        else None
      end)
    (fun (function_parameter : unit) ⇒
      let '_ := function_parameter in
      Build_extensible "Sc_rollup_invalid_serialized_inbox_proof" unit tt).

Records for the constructor parameters
Module ConstructorRecords_reveal_proof.
  Module reveal_proof.
    Module Dal_page_proof.
      Record record {page_id proof : Set} : Set := Build {
        page_id : page_id;
        proof : proof;
      }.
      Arguments record : clear implicits.
      Definition with_page_id {t_page_id t_proof} page_id
        (r : record t_page_id t_proof) :=
        Build t_page_id t_proof page_id r.(proof).
      Definition with_proof {t_page_id t_proof} proof
        (r : record t_page_id t_proof) :=
        Build t_page_id t_proof r.(page_id) proof.
    End Dal_page_proof.
    Definition Dal_page_proof_skeleton := Dal_page_proof.record.
  End reveal_proof.
End ConstructorRecords_reveal_proof.
Import ConstructorRecords_reveal_proof.

Reserved Notation "'reveal_proof.Dal_page_proof".

Inductive reveal_proof : Set :=
| Raw_data_proof : string reveal_proof
| Metadata_proof : reveal_proof
| Dal_page_proof : 'reveal_proof.Dal_page_proof reveal_proof

where "'reveal_proof.Dal_page_proof" :=
  (reveal_proof.Dal_page_proof_skeleton Dal_slot_repr.Page.t
    Dal_slot_repr.History.proof).

Module reveal_proof.
  Include ConstructorRecords_reveal_proof.reveal_proof.
  Definition Dal_page_proof := 'reveal_proof.Dal_page_proof.
End reveal_proof.

Definition reveal_proof_encoding : Data_encoding.encoding reveal_proof :=
  let case_raw_data : Data_encoding.case reveal_proof :=
    Data_encoding.case_value "raw data proof" None (Data_encoding.Tag 0)
      (Data_encoding.obj2
        (Data_encoding.req None None "reveal_proof_kind"
          (Data_encoding.constant "raw_data_proof"))
        (Data_encoding.req None None "raw_data"
          (Data_encoding.check_size Constants_repr.sc_rollup_message_size_limit
            (Data_encoding.string' None Data_encoding.Hex))))
      (fun (function_parameter : reveal_proof) ⇒
        match function_parameter with
        | Raw_data_proof s_valueSome (tt, s_value)
        | _None
        end)
      (fun (function_parameter : unit × string) ⇒
        let '(_, s_value) := function_parameter in
        Raw_data_proof s_value)
  in let case_metadata_proof : Data_encoding.case reveal_proof :=
    Data_encoding.case_value "metadata proof" None (Data_encoding.Tag 1)
      (Data_encoding.obj1
        (Data_encoding.req None None "reveal_proof_kind"
          (Data_encoding.constant "metadata_proof")))
      (fun (function_parameter : reveal_proof) ⇒
        match function_parameter with
        | Metadata_proofSome tt
        | _None
        end)
      (fun (function_parameter : unit) ⇒
        let '_ := function_parameter in
        Metadata_proof) in
  let case_dal_page :=
    Data_encoding.case_value "dal page proof" None (Data_encoding.Tag 2)
      (Data_encoding.obj3
        (Data_encoding.req None None "reveal_proof_kind"
          (Data_encoding.constant "dal_page_proof"))
        (Data_encoding.req None None "dal_page_id" Dal_slot_repr.Page.encoding)
        (Data_encoding.req None None "dal_proof"
          Dal_slot_repr.History.proof_encoding))
      (fun (function_parameter : reveal_proof) ⇒
        match function_parameter with
        |
          Dal_page_proof {|
            reveal_proof.Dal_page_proof.page_id := page_id;
              reveal_proof.Dal_page_proof.proof := proof_value
              |} ⇒ Some (tt, page_id, proof_value)
        | _None
        end)
      (fun (function_parameter :
        unit × Dal_slot_repr.Page.t × Dal_slot_repr.History.proof) ⇒
        let '(_, page_id, proof_value) := function_parameter in
        Dal_page_proof
          {| reveal_proof.Dal_page_proof.page_id := page_id;
            reveal_proof.Dal_page_proof.proof := proof_value; |}) in
  Data_encoding.union None [ case_raw_data; case_metadata_proof; case_dal_page ].

Records for the constructor parameters
Module ConstructorRecords_input_proof.
  Module input_proof.
    Module Inbox_proof.
      Record record {level message_counter proof : Set} : Set := Build {
        level : level;
        message_counter : message_counter;
        proof : proof;
      }.
      Arguments record : clear implicits.
      Definition with_level {t_level t_message_counter t_proof} level
        (r : record t_level t_message_counter t_proof) :=
        Build t_level t_message_counter t_proof level r.(message_counter)
          r.(proof).
      Definition with_message_counter {t_level t_message_counter t_proof}
        message_counter (r : record t_level t_message_counter t_proof) :=
        Build t_level t_message_counter t_proof r.(level) message_counter
          r.(proof).
      Definition with_proof {t_level t_message_counter t_proof} proof
        (r : record t_level t_message_counter t_proof) :=
        Build t_level t_message_counter t_proof r.(level) r.(message_counter)
          proof.
    End Inbox_proof.
    Definition Inbox_proof_skeleton := Inbox_proof.record.
  End input_proof.
End ConstructorRecords_input_proof.
Import ConstructorRecords_input_proof.

Reserved Notation "'input_proof.Inbox_proof".

Inductive input_proof : Set :=
| Inbox_proof : 'input_proof.Inbox_proof input_proof
| Reveal_proof : reveal_proof input_proof
| First_inbox_message : input_proof

where "'input_proof.Inbox_proof" :=
  (input_proof.Inbox_proof_skeleton Raw_level_repr.t Z.t
    Sc_rollup_inbox_repr.serialized_proof).

Module input_proof.
  Include ConstructorRecords_input_proof.input_proof.
  Definition Inbox_proof := 'input_proof.Inbox_proof.
End input_proof.

Definition input_proof_encoding : Data_encoding.encoding input_proof :=
  let proof_kind (kind_value : string) : Data_encoding.field unit :=
    Data_encoding.req None None "input_proof_kind"
      (Data_encoding.constant kind_value) in
  let case_inbox_proof :=
    Data_encoding.case_value "inbox proof" None (Data_encoding.Tag 0)
      (Data_encoding.obj4 (proof_kind "inbox_proof")
        (Data_encoding.req None None "level" Raw_level_repr.encoding)
        (Data_encoding.req None None "message_counter" Data_encoding.n_value)
        (Data_encoding.req None None "serialized_proof"
          Sc_rollup_inbox_repr.serialized_proof_encoding))
      (fun (function_parameter : input_proof) ⇒
        match function_parameter with
        |
          Inbox_proof {|
            input_proof.Inbox_proof.level := level;
              input_proof.Inbox_proof.message_counter := message_counter;
              input_proof.Inbox_proof.proof := proof_value
              |} ⇒ Some (tt, level, message_counter, proof_value)
        | _None
        end)
      (fun (function_parameter :
        unit × Raw_level_repr.raw_level × Z.t ×
          Sc_rollup_inbox_repr.serialized_proof) ⇒
        let '(_, level, message_counter, proof_value) := function_parameter in
        Inbox_proof
          {| input_proof.Inbox_proof.level := level;
            input_proof.Inbox_proof.message_counter := message_counter;
            input_proof.Inbox_proof.proof := proof_value; |}) in
  let case_reveal_proof :=
    Data_encoding.case_value "reveal proof" None (Data_encoding.Tag 1)
      (Data_encoding.obj2 (proof_kind "reveal_proof")
        (Data_encoding.req None None "reveal_proof" reveal_proof_encoding))
      (fun (function_parameter : input_proof) ⇒
        match function_parameter with
        | Reveal_proof s_valueSome (tt, s_value)
        | _None
        end)
      (fun (function_parameter : unit × reveal_proof) ⇒
        let '(_, s_value) := function_parameter in
        Reveal_proof s_value) in
  let first_input :=
    Data_encoding.case_value "first input" None (Data_encoding.Tag 2)
      (Data_encoding.obj1 (proof_kind "first_input"))
      (fun (function_parameter : input_proof) ⇒
        match function_parameter with
        | First_inbox_messageSome tt
        | _None
        end)
      (fun (function_parameter : unit) ⇒
        let '_ := function_parameter in
        First_inbox_message) in
  Data_encoding.union None [ case_inbox_proof; case_reveal_proof; first_input ].

Module t.
  Record record : Set := Build {
    pvm_step : Sc_rollups.wrapped_proof;
    input_proof : option input_proof;
  }.
  Definition with_pvm_step pvm_step (r : record) :=
    Build pvm_step r.(input_proof).
  Definition with_input_proof input_proof (r : record) :=
    Build r.(pvm_step) input_proof.
End t.
Definition t := t.record.

Definition encoding : Data_encoding.encoding t :=
  Data_encoding.conv
    (fun (function_parameter : t) ⇒
      let '{| t.pvm_step := pvm_step; t.input_proof := input_proof |} :=
        function_parameter in
      (pvm_step, input_proof))
    (fun (function_parameter : Sc_rollups.wrapped_proof × option input_proof) ⇒
      let '(pvm_step, input_proof) := function_parameter in
      {| t.pvm_step := pvm_step; t.input_proof := input_proof; |}) None
    (Data_encoding.obj2
      (Data_encoding.req None None "pvm_step" Sc_rollups.wrapped_proof_encoding)
      (Data_encoding.opt None None "input_proof" input_proof_encoding)).

Definition pp {A : Set} (ppf : Format.formatter) (function_parameter : A)
  : unit :=
  let '_ := function_parameter in
  Format.fprintf ppf
    (CamlinternalFormatBasics.Format
      (CamlinternalFormatBasics.String_literal "Refutation game proof"
        CamlinternalFormatBasics.End_of_format) "Refutation game proof").

Definition start (proof_value : t) : Sc_rollup_repr.State_hash.t :=
  let P := Sc_rollups.wrapped_proof_module proof_value.(t.pvm_step) in
  let 'existS _ _ P := P in
  P.(Sc_rollups.PVM_with_proof.proof_start_state)
    P.(Sc_rollups.PVM_with_proof.proof_val).

Definition stop (proof_value : t) : Sc_rollup_repr.State_hash.t :=
  let P := Sc_rollups.wrapped_proof_module proof_value.(t.pvm_step) in
  let 'existS _ _ P := P in
  P.(Sc_rollups.PVM_with_proof.proof_stop_state)
    P.(Sc_rollups.PVM_with_proof.proof_val).

Definition cut_at_level
  (origination_level : Raw_level_repr.raw_level)
  (commit_level : Raw_level_repr.raw_level) (input : Sc_rollup_PVM_sig.input)
  : option Sc_rollup_PVM_sig.input :=
  match input with
  |
    Sc_rollup_PVM_sig.Inbox_message {|
      Sc_rollup_PVM_sig.inbox_message.inbox_level := input_level |} ⇒
    if
      (Raw_level_repr.op_lteq input_level origination_level) ||
      (Raw_level_repr.op_lteq commit_level input_level)
    then
      None
    else
      Some input
  | Sc_rollup_PVM_sig.Reveal _dataSome input
  end.

Definition proof_error {A : Set} (reason_value : string) : M? A :=
  Error_monad.Lwt_result_syntax.tzfail
    (Build_extensible "Sc_rollup_proof_check" string reason_value).

Definition check (p_value : bool) (reason_value : string) : M? unit :=
  if p_value then
    return? tt
  else
    proof_error reason_value.

Definition check_inbox_proof
  (snapshot_value : Sc_rollup_inbox_repr.history_proof)
  (serialized_inbox_proof : Sc_rollup_inbox_repr.serialized_proof)
  (function_parameter : Raw_level_repr.t × Z.t)
  : M? (option Sc_rollup_PVM_sig.inbox_message) :=
  let '(level, counter) := function_parameter in
  match Sc_rollup_inbox_repr.of_serialized_proof serialized_inbox_proof with
  | None
    Error_monad.error_value
      (Build_extensible "Sc_rollup_invalid_serialized_inbox_proof" unit tt)
  | Some inbox_proof
    Sc_rollup_inbox_repr.verify_proof (level, counter) snapshot_value
      inbox_proof
  end.

Module Dal_proofs.
Given a page, identified by its ID, we accept to produce or verify a proof for it if, and only if, the page's level [page_published_level] is in the following boundaries: page_published_level > origination_level: this means that the slot of the page was published after the rollup origination ; page_published_level + dal_attestation_lag < commit_level: this means that the slot of the page has been confirmed before the [commit_level]. According to the definition in {!Sc_rollup_commitment_repr}, [commit_level] (aka inbox_level in that module) is the level (excluded) up to which the PVM consumed all messages and DAL/DAC inputs before producing the related commitment.
  Definition page_level_is_valid
    (dal_attestation_lag : int) (origination_level : Raw_level_repr.raw_level)
    (commit_level : Raw_level_repr.raw_level) (page_id : Dal_slot_repr.Page.t)
    : M? bool :=
    let page_published_level :=
      page_id.(Dal_slot_repr.Page.t.slot_id).(Dal_slot_repr.Header.id.published_level)
      in
    let not_too_old :=
      Raw_level_repr.op_gt page_published_level origination_level in
    let? page_published_level_with_lag :=
      Raw_level_repr.add page_published_level dal_attestation_lag in
    let not_too_recent :=
      Raw_level_repr.op_lt page_published_level_with_lag commit_level in
    return? (not_too_old && not_too_recent).

  Definition verify
    (metadata : Sc_rollup_metadata_repr.t) (dal_attestation_lag : int)
    (commit_level : Raw_level_repr.raw_level)
    (dal_parameters : Dal_slot_repr.parameters) (page_id : Dal_slot_repr.Page.t)
    (dal_snapshot : Dal_slot_repr.History.t)
    (proof_value : Dal_slot_repr.History.proof)
    : M? (option Sc_rollup_PVM_sig.input) :=
    let? is_valid :=
      page_level_is_valid dal_attestation_lag
        metadata.(Sc_rollup_metadata_repr.t.origination_level) commit_level
        page_id in
    if is_valid then
      let? input :=
        Dal_slot_repr.History.verify_proof dal_parameters page_id dal_snapshot
          proof_value in
      Error_monad.Result_syntax.return_some
        (Sc_rollup_PVM_sig.Reveal (Sc_rollup_PVM_sig.Dal_page input))
    else
      Error_monad.Result_syntax.return_none.

  Definition produce
    (metadata : Sc_rollup_metadata_repr.t) (dal_attestation_lag : int)
    (commit_level : Raw_level_repr.raw_level)
    (dal_parameters : Dal_slot_repr.parameters) (page_id : Dal_slot_repr.Page.t)
    (page_info : option (Dal_slot_repr.Page.content × Dal_slot_repr.Page.proof))
    (confirmed_slots_history : Dal_slot_repr.History.t)
    (history_cache :
      Dal_slot_repr.History.History_cache.(Bounded_history_repr.S.t))
    : M? (option input_proof × option Sc_rollup_PVM_sig.input) :=
    let? is_valid :=
      page_level_is_valid dal_attestation_lag
        metadata.(Sc_rollup_metadata_repr.t.origination_level) commit_level
        page_id in
    if is_valid then
      let? '(proof_value, content_opt) :=
        Dal_slot_repr.History.produce_proof dal_parameters page_id page_info
          confirmed_slots_history history_cache in
      return?
        ((Some
          (Reveal_proof
            (Dal_page_proof
              {| reveal_proof.Dal_page_proof.page_id := page_id;
                reveal_proof.Dal_page_proof.proof := proof_value; |}))),
          (Some
            (Sc_rollup_PVM_sig.Reveal (Sc_rollup_PVM_sig.Dal_page content_opt))))
    else
      return? (None, None).
End Dal_proofs.

Definition valid
  (metadata : Sc_rollup_metadata_repr.t)
  (snapshot_value : Sc_rollup_inbox_repr.history_proof)
  (commit_level : Raw_level_repr.raw_level)
  (dal_snapshot : Dal_slot_repr.History.t)
  (dal_parameters : Dal_slot_repr.parameters) (dal_attestation_lag : int)
  (pvm_name : String.t) (proof_value : t)
  : M? (option Sc_rollup_PVM_sig.input × Sc_rollup_PVM_sig.input_request) :=
  let P := Sc_rollups.wrapped_proof_module proof_value.(t.pvm_step) in
  let 'existS _ _ P := P in
  let? '_ :=
    check (String.equal P.(Sc_rollups.PVM_with_proof.name) pvm_name)
      "Incorrect PVM kind" in
  let origination_level :=
    metadata.(Sc_rollup_metadata_repr.t.origination_level) in
  let? input :=
    match proof_value.(t.input_proof) with
    | NoneError_monad.Lwt_result_syntax.return_none
    |
      Some
        (Inbox_proof {|
          input_proof.Inbox_proof.level := level;
            input_proof.Inbox_proof.message_counter := message_counter;
            input_proof.Inbox_proof.proof := proof_value
            |}) ⇒
      let? inbox_message :=
        check_inbox_proof snapshot_value proof_value
          (level, (Z.succ message_counter)) in
      return?
        (Option.map
          (fun (i_value : Sc_rollup_PVM_sig.inbox_message) ⇒
            Sc_rollup_PVM_sig.Inbox_message i_value) inbox_message)
    | Some First_inbox_message
      let? payload :=
        Sc_rollup_inbox_message_repr.serialize
          (Sc_rollup_inbox_message_repr.Internal
            Sc_rollup_inbox_message_repr.Start_of_level) in
      let inbox_level := Raw_level_repr.succ origination_level in
      let message_counter := Z.zero in
      Error_monad.Lwt_result_syntax.return_some
        (Sc_rollup_PVM_sig.Inbox_message
          {| Sc_rollup_PVM_sig.inbox_message.inbox_level := inbox_level;
            Sc_rollup_PVM_sig.inbox_message.message_counter := message_counter;
            Sc_rollup_PVM_sig.inbox_message.payload := payload; |})
    | Some (Reveal_proof (Raw_data_proof data)) ⇒
      Error_monad.Lwt_result_syntax.return_some
        (Sc_rollup_PVM_sig.Reveal (Sc_rollup_PVM_sig.Raw_data data))
    | Some (Reveal_proof Metadata_proof) ⇒
      Error_monad.Lwt_result_syntax.return_some
        (Sc_rollup_PVM_sig.Reveal (Sc_rollup_PVM_sig.Metadata metadata))
    |
      Some
        (Reveal_proof
          (Dal_page_proof {|
            reveal_proof.Dal_page_proof.page_id := page_id;
              reveal_proof.Dal_page_proof.proof := proof_value
              |})) ⇒
      Dal_proofs.verify metadata dal_attestation_lag commit_level dal_parameters
        page_id dal_snapshot proof_value
    end in
  let input := Option.bind input (cut_at_level origination_level commit_level)
    in
  let? input_requested :=
    P.(Sc_rollups.PVM_with_proof.verify_proof) input
      P.(Sc_rollups.PVM_with_proof.proof_val) in
  let? '_ :=
    match (proof_value.(t.input_proof), input_requested) with
    | (None, Sc_rollup_PVM_sig.No_input_required)
      Error_monad.Lwt_result_syntax.return_unit
    | (Some First_inbox_message, Sc_rollup_PVM_sig.Initial)
      Error_monad.Lwt_result_syntax.return_unit
    |
      (Some
        (Inbox_proof {|
          input_proof.Inbox_proof.level := level;
            input_proof.Inbox_proof.message_counter := message_counter;
            input_proof.Inbox_proof.proof := _
            |}), Sc_rollup_PVM_sig.First_after l_value n_value)
      check
        ((Raw_level_repr.op_eq level l_value) &&
        (Z.equal message_counter n_value))
        "Level and index of inbox proof are not equal to the one expected in input request."
    |
      (Some (Reveal_proof (Raw_data_proof data)),
        Sc_rollup_PVM_sig.Needs_reveal
          (Sc_rollup_PVM_sig.Reveal_raw_data expected_hash))
      let data_hash := Sc_rollup_PVM_sig.Reveal_hash.hash_string None [ data ]
        in
      check (Sc_rollup_PVM_sig.Reveal_hash.equal data_hash expected_hash)
        "Invalid reveal"
    |
      (Some (Reveal_proof Metadata_proof),
        Sc_rollup_PVM_sig.Needs_reveal Sc_rollup_PVM_sig.Reveal_metadata)
      Error_monad.Lwt_result_syntax.return_unit
    |
      (Some
        (Reveal_proof
          (Dal_page_proof {|
            reveal_proof.Dal_page_proof.page_id := page_id;
              reveal_proof.Dal_page_proof.proof := _
              |})),
        Sc_rollup_PVM_sig.Needs_reveal (Sc_rollup_PVM_sig.Request_dal_page pid))
      ⇒
      check (Dal_slot_repr.Page.equal page_id pid)
        "Dal proof's page ID is not the one expected in input request."
    |
      ((None,
        (Sc_rollup_PVM_sig.Initial | Sc_rollup_PVM_sig.First_after _ _ |
        Sc_rollup_PVM_sig.Needs_reveal _)) |
      (Some _, Sc_rollup_PVM_sig.No_input_required) |
      (Some (Inbox_proof _), Sc_rollup_PVM_sig.Needs_reveal _) | _) ⇒
      proof_error "Inbox proof and input request are dissociated."
    end in
  return? (input, input_requested).

Module PVM_with_context_and_state.
  Record signature {state context proof output_proof : Set} : Set := {
    name : string;
    parse_boot_sector : string option Sc_rollups.PVM.boot_sector;
    pp_boot_sector : Format.formatter Sc_rollups.PVM.boot_sector unit;
    state := state;
    pp : state (Format.formatter unit unit);
    context := context;
    hash := Sc_rollup_repr.State_hash.t;
    proof := proof;
    proof_encoding : Data_encoding.t proof;
    proof_start_state : proof hash;
    proof_stop_state : proof hash;
    state_hash : state hash;
    initial_state : state state;
    install_boot_sector : state string state;
    is_input_state : state Sc_rollup_PVM_sig.input_request;
    set_input : Sc_rollup_PVM_sig.input state state;
    eval : state state;
    verify_proof :
      option Sc_rollup_PVM_sig.input proof
      M? Sc_rollup_PVM_sig.input_request;
    produce_proof :
      context option Sc_rollup_PVM_sig.input state M? proof;
    verify_origination_proof : proof string bool;
    produce_origination_proof : context string M? proof;
    output_proof := output_proof;
    output_proof_encoding : Data_encoding.t output_proof;
    output_of_output_proof : output_proof Sc_rollup_PVM_sig.output;
    state_of_output_proof : output_proof hash;
    verify_output_proof : output_proof bool;
    produce_output_proof :
      context state Sc_rollup_PVM_sig.output
      Pervasives.result output_proof Error_monad._error;
    Internal_for_tests_insert_failure : state state;
    context_value : context;
    state_value : state;
    reveal : Sc_rollup_PVM_sig.Reveal_hash.t option string;
    Inbox_with_history_inbox : Sc_rollup_inbox_repr.history_proof;
    Inbox_with_history_history :
      Sc_rollup_inbox_repr.History.(Bounded_history_repr.S.t);
    Inbox_with_history_get_level_tree_history :
      Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t
      Sc_rollup_inbox_merkelized_payload_hashes_repr.History.t;
    Dal_with_history_confirmed_slots_history : Dal_slot_repr.History.t;
    Dal_with_history_history_cache :
      Dal_slot_repr.History.History_cache.(Bounded_history_repr.S.t);
    Dal_with_history_page_info :
      option (Dal_slot_repr.Page.content × Dal_slot_repr.Page.proof);
    Dal_with_history_dal_parameters : Dal_slot_repr.parameters;
    Dal_with_history_dal_attestation_lag : int;
  }.
End PVM_with_context_and_state.
Definition PVM_with_context_and_state := @PVM_with_context_and_state.signature.
Arguments PVM_with_context_and_state {_ _ _ _}.

Definition produce
  (metadata : Sc_rollup_metadata_repr.t)
  (pvm_and_state :
    {'[state, context, proof, output_proof] : [Set ** Set ** Set ** Set] @
      PVM_with_context_and_state (state := state) (context := context)
        (proof := proof) (output_proof := output_proof)})
  (commit_level : Raw_level_repr.raw_level) : M? t :=
  let 'P := pvm_and_state in
  let 'existS _ _ P := P in
  let 'request :=
    P.(PVM_with_context_and_state.is_input_state)
      P.(PVM_with_context_and_state.state_value) in
  let origination_level :=
    metadata.(Sc_rollup_metadata_repr.t.origination_level) in
  let? '(input_proof, input_given) :=
    match request with
    | Sc_rollup_PVM_sig.No_input_requiredreturn? (None, None)
    | Sc_rollup_PVM_sig.Initial
      let? input :=
        let? payload :=
          Sc_rollup_inbox_message_repr.serialize
            (Sc_rollup_inbox_message_repr.Internal
              Sc_rollup_inbox_message_repr.Start_of_level) in
        let inbox_level := Raw_level_repr.succ origination_level in
        let message_counter := Z.zero in
        Error_monad.Lwt_result_syntax.return_some
          (Sc_rollup_PVM_sig.Inbox_message
            {| Sc_rollup_PVM_sig.inbox_message.inbox_level := inbox_level;
              Sc_rollup_PVM_sig.inbox_message.message_counter :=
                message_counter;
              Sc_rollup_PVM_sig.inbox_message.payload := payload; |}) in
      let inbox_proof := First_inbox_message in
      return? ((Some inbox_proof), input)
    | Sc_rollup_PVM_sig.First_after level message_counter
      let? '(inbox_proof, input) :=
        Sc_rollup_inbox_repr.produce_proof
          P.(PVM_with_context_and_state.Inbox_with_history_get_level_tree_history)
          P.(PVM_with_context_and_state.Inbox_with_history_history)
          P.(PVM_with_context_and_state.Inbox_with_history_inbox)
          (level, (Z.succ message_counter)) in
      let input :=
        Option.map
          (fun (msg : Sc_rollup_PVM_sig.inbox_message) ⇒
            Sc_rollup_PVM_sig.Inbox_message msg) input in
      let inbox_proof :=
        Inbox_proof
          {| input_proof.Inbox_proof.level := level;
            input_proof.Inbox_proof.message_counter := message_counter;
            input_proof.Inbox_proof.proof :=
              Sc_rollup_inbox_repr.to_serialized_proof inbox_proof; |} in
      return? ((Some inbox_proof), input)
    | Sc_rollup_PVM_sig.Needs_reveal (Sc_rollup_PVM_sig.Reveal_raw_data h_value)
      ⇒
      let res := P.(PVM_with_context_and_state.reveal) h_value in
      match res with
      | Noneproof_error "No reveal"
      | Some data
        return?
          ((Some (Reveal_proof (Raw_data_proof data))),
            (Some (Sc_rollup_PVM_sig.Reveal (Sc_rollup_PVM_sig.Raw_data data))))
      end
    | Sc_rollup_PVM_sig.Needs_reveal Sc_rollup_PVM_sig.Reveal_metadata
      return?
        ((Some (Reveal_proof Metadata_proof)),
          (Some (Sc_rollup_PVM_sig.Reveal (Sc_rollup_PVM_sig.Metadata metadata))))
    |
      Sc_rollup_PVM_sig.Needs_reveal
        (Sc_rollup_PVM_sig.Request_dal_page page_id) ⇒
      Dal_proofs.produce metadata
        P.(PVM_with_context_and_state.Dal_with_history_dal_attestation_lag)
        commit_level
        P.(PVM_with_context_and_state.Dal_with_history_dal_parameters) page_id
        P.(PVM_with_context_and_state.Dal_with_history_page_info)
        P.(PVM_with_context_and_state.Dal_with_history_confirmed_slots_history)
        P.(PVM_with_context_and_state.Dal_with_history_history_cache)
    end in
  let input_given :=
    Option.bind input_given (cut_at_level origination_level commit_level) in
  let? pvm_step_proof :=
    P.(PVM_with_context_and_state.produce_proof)
      P.(PVM_with_context_and_state.context_value) input_given
      P.(PVM_with_context_and_state.state_value) in
  let P_with_proof :=
    let name := P.(PVM_with_context_and_state.name) in
    let parse_boot_sector := P.(PVM_with_context_and_state.parse_boot_sector) in
    let pp_boot_sector := P.(PVM_with_context_and_state.pp_boot_sector) in
    let state := P.(PVM_with_context_and_state.state) in
    let pp := P.(PVM_with_context_and_state.pp) in
    let context := P.(PVM_with_context_and_state.context) in
    let hash := P.(PVM_with_context_and_state.hash) in
    let proof := P.(PVM_with_context_and_state.proof) in
    let proof_encoding := P.(PVM_with_context_and_state.proof_encoding) in
    let proof_start_state := P.(PVM_with_context_and_state.proof_start_state) in
    let proof_stop_state := P.(PVM_with_context_and_state.proof_stop_state) in
    let state_hash := P.(PVM_with_context_and_state.state_hash) in
    let initial_state := P.(PVM_with_context_and_state.initial_state) in
    let install_boot_sector :=
      P.(PVM_with_context_and_state.install_boot_sector) in
    let is_input_state := P.(PVM_with_context_and_state.is_input_state) in
    let set_input := P.(PVM_with_context_and_state.set_input) in
    let eval := P.(PVM_with_context_and_state.eval) in
    let verify_proof := P.(PVM_with_context_and_state.verify_proof) in
    let produce_proof := P.(PVM_with_context_and_state.produce_proof) in
    let verify_origination_proof :=
      P.(PVM_with_context_and_state.verify_origination_proof) in
    let produce_origination_proof :=
      P.(PVM_with_context_and_state.produce_origination_proof) in
    let output_proof := P.(PVM_with_context_and_state.output_proof) in
    let output_proof_encoding :=
      P.(PVM_with_context_and_state.output_proof_encoding) in
    let output_of_output_proof :=
      P.(PVM_with_context_and_state.output_of_output_proof) in
    let state_of_output_proof :=
      P.(PVM_with_context_and_state.state_of_output_proof) in
    let verify_output_proof :=
      P.(PVM_with_context_and_state.verify_output_proof) in
    let produce_output_proof :=
      P.(PVM_with_context_and_state.produce_output_proof) in
    let context_value := P.(PVM_with_context_and_state.context_value) in
    let state_value := P.(PVM_with_context_and_state.state_value) in
    let reveal := P.(PVM_with_context_and_state.reveal) in
    let proof_val := pvm_step_proof in
    {|
      Sc_rollups.PVM_with_proof.name := name;
      Sc_rollups.PVM_with_proof.parse_boot_sector := parse_boot_sector;
      Sc_rollups.PVM_with_proof.pp_boot_sector := pp_boot_sector;
      Sc_rollups.PVM_with_proof.pp := pp;
      Sc_rollups.PVM_with_proof.proof_encoding := proof_encoding;
      Sc_rollups.PVM_with_proof.proof_start_state := proof_start_state;
      Sc_rollups.PVM_with_proof.proof_stop_state := proof_stop_state;
      Sc_rollups.PVM_with_proof.state_hash := state_hash;
      Sc_rollups.PVM_with_proof.initial_state := initial_state;
      Sc_rollups.PVM_with_proof.install_boot_sector := install_boot_sector;
      Sc_rollups.PVM_with_proof.is_input_state := is_input_state;
      Sc_rollups.PVM_with_proof.set_input := set_input;
      Sc_rollups.PVM_with_proof.eval := eval;
      Sc_rollups.PVM_with_proof.verify_proof := verify_proof;
      Sc_rollups.PVM_with_proof.produce_proof := produce_proof;
      Sc_rollups.PVM_with_proof.verify_origination_proof :=
        verify_origination_proof;
      Sc_rollups.PVM_with_proof.produce_origination_proof :=
        produce_origination_proof;
      Sc_rollups.PVM_with_proof.output_proof_encoding := output_proof_encoding;
      Sc_rollups.PVM_with_proof.output_of_output_proof := output_of_output_proof;
      Sc_rollups.PVM_with_proof.state_of_output_proof := state_of_output_proof;
      Sc_rollups.PVM_with_proof.verify_output_proof := verify_output_proof;
      Sc_rollups.PVM_with_proof.produce_output_proof := produce_output_proof;
      Sc_rollups.PVM_with_proof.proof_val := proof_val
    |} in
  match
    Sc_rollups.wrap_proof
      (existS (A := [Set ** Set ** Set ** Set]) _ [_, _, _, _] P_with_proof)
    with
  | Some pvm_step
    return? {| t.pvm_step := pvm_step; t.input_proof := input_proof; |}
  | Noneproof_error "Could not wrap proof"
  end.