diff --git a/src/lib_layer2_irmin_context/irmin_context.ml b/src/lib_layer2_irmin_context/irmin_context.ml index 2922afa374dce27683ee7b7d8c14581a7a1a7a01..a07e902acb097b049b755b6da10b683bb4565cdc 100644 --- a/src/lib_layer2_irmin_context/irmin_context.ml +++ b/src/lib_layer2_irmin_context/irmin_context.ml @@ -272,6 +272,8 @@ struct let (`Value hash | `Node hash) = proof.IStoreProof.Proof.after in Hash.of_context_hash hash + let cast_read_only proof = IStoreProof.Proof.{proof with after = proof.before} + let produce_proof index tree step = let open Lwt_syntax in (* Committing the context is required by Irmin to produce valid proofs. *) diff --git a/src/lib_layer2_irmin_context/irmin_context.mli b/src/lib_layer2_irmin_context/irmin_context.mli index c7a9b612a0f859a073d8dfe3de175ac4f8b88f53..34f20b82bbffbff41d4cb9434a76f0aff78449ac 100644 --- a/src/lib_layer2_irmin_context/irmin_context.mli +++ b/src/lib_layer2_irmin_context/irmin_context.mli @@ -197,6 +197,9 @@ end) : sig [rpoof]. *) val proof_after : proof -> Hash.t + (** [cast_read_only] replaces [proof.after] with [proof.before]. *) + val cast_read_only : proof -> proof + (** [produce_proof ctxt tree f] produces and returns a proof for the execution of [f] on the state [tree]. *) val produce_proof : diff --git a/src/proto_alpha/lib_benchmarks_proto/sc_rollup_benchmarks.ml b/src/proto_alpha/lib_benchmarks_proto/sc_rollup_benchmarks.ml index 2ee44ac1746da5723d16dea0036dbb22a964fb21..5a9d95ab8cdc3d223591ef660f6901980a585be8 100644 --- a/src/proto_alpha/lib_benchmarks_proto/sc_rollup_benchmarks.ml +++ b/src/proto_alpha/lib_benchmarks_proto/sc_rollup_benchmarks.ml @@ -83,6 +83,8 @@ module Pvm_state_generator = struct let proof_after proof = kinded_hash_to_state_hash proof.Context.Proof.after + let cast_read_only proof = Context.Proof.{proof with after = proof.before} + let proof_encoding = let module Proof_encoding = Tezos_context_merkle_proof_encoding.Merkle_proof_encoding diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 902325b48df22f4a1dff0ec978e3edd262df393c..418391a21e13b46d232c2a7e9bd5f0ee060a7cbb 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -3823,7 +3823,7 @@ module Sc_rollup : sig | Dissection_invalid_successive_states_shape end - module type Generic_pvm_context_sig = sig + module type Generic_irmin_pvm_context_sig = sig module Tree : Context.TREE with type key = string list and type value = bytes @@ -3837,6 +3837,8 @@ module Sc_rollup : sig val proof_after : proof -> Sc_rollup_repr.State_hash.t + val cast_read_only : proof -> proof + val verify_proof : proof -> (tree -> (tree * 'a) Lwt.t) -> (tree * 'a) option Lwt.t @@ -3882,6 +3884,9 @@ module Sc_rollup : sig proof -> input_request tzresult Lwt.t + val get_proof_state_level : + proof -> Raw_level_repr.t option tzresult Lwt.t + type output_proof val output_proof_encoding : output_proof Data_encoding.t @@ -3960,7 +3965,7 @@ module Sc_rollup : sig val genesis_state_hash_of : boot_sector:string -> Kind.t -> State_hash.t Lwt.t module ArithPVM : sig - module Make (C : Generic_pvm_context_sig) : sig + module Make (C : Generic_irmin_pvm_context_sig) : sig include PVM.S with type context = C.Tree.t @@ -4004,7 +4009,9 @@ module Sc_rollup : sig module type Make_wasm = module type of Wasm_2_0_0.Make - module Make (Wasm_backend : Make_wasm) (C : Generic_pvm_context_sig) : sig + module Make + (Wasm_backend : Make_wasm) + (C : Generic_irmin_pvm_context_sig) : sig include PVM.S with type context = C.Tree.t @@ -4194,10 +4201,9 @@ module Sc_rollup : sig Inbox.history_proof -> Raw_level.t -> Dal.Slots_history.t -> - Dal.parameters -> + find_dal_parameters: + (Raw_level.t -> Constants.Parametric.dal tzresult Lwt.t) -> dal_activation_level:Raw_level.t option -> - dal_attestation_lag:int -> - dal_number_of_slots:int -> is_reveal_enabled:is_reveal_enabled -> dal_attested_slots_validity_lag:int -> 'proof t -> @@ -4205,6 +4211,8 @@ module Sc_rollup : sig val produce : metadata:Metadata.t -> + find_dal_parameters: + (Raw_level.t -> Constants.Parametric.dal tzresult Lwt.t) -> (module PVM_with_context_and_state) -> Raw_level.t -> is_reveal_enabled:is_reveal_enabled -> @@ -4316,10 +4324,9 @@ module Sc_rollup : sig val play : Kind.t -> - Dal.parameters -> dal_activation_level:Raw_level.t option -> - dal_attestation_lag:int -> - dal_number_of_slots:int -> + find_dal_parameters: + (Raw_level.t -> Constants.Parametric.dal tzresult Lwt.t) -> stakers:Index.t -> Metadata.t -> t -> diff --git a/src/proto_alpha/lib_protocol/sc_rollup_PVM_sig.ml b/src/proto_alpha/lib_protocol/sc_rollup_PVM_sig.ml index a09378687b85ec392bb1adb96d1cefe2785d7f3c..7095283381312d5aa56f43acadc9095032068c9d 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_PVM_sig.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_PVM_sig.ml @@ -655,6 +655,9 @@ module type PROTO_VERIFICATION = sig proof -> input_request tzresult Lwt.t + (** [get_proof_state_level proof] returns the tezos level of the proof inner state. *) + val get_proof_state_level : proof -> Raw_level_repr.t option tzresult Lwt.t + (** The following type is inhabited by the proofs that a given [output] is part of the outbox of a given [state]. *) type output_proof @@ -735,7 +738,7 @@ module type S = sig end end -module type Generic_pvm_context_sig = sig +module type Generic_irmin_pvm_context_sig = sig module Tree : Context.TREE with type key = string list and type value = bytes type tree = Tree.tree @@ -748,6 +751,12 @@ module type Generic_pvm_context_sig = sig val proof_after : proof -> Sc_rollup_repr.State_hash.t + (** [cast_read_only proof] replaces [proof.after] with [proof.before]. + This allows to use {!verify_proof} with another step transition to read + the inner state of the proof. This leaks abstraction on how Irmin proof + verification work. *) + val cast_read_only : proof -> proof + val verify_proof : proof -> (tree -> (tree * 'a) Lwt.t) -> (tree * 'a) option Lwt.t diff --git a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml index cd74a5390e2871bf8c39db2843d817218c02afe4..a3fda8e8e1e0b12ba2c181ffc64e9e7a986b0c49 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml @@ -112,7 +112,7 @@ module type S = sig val get_is_stuck : state -> string option Lwt.t end -module Make (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : +module Make (Context : Sc_rollup_PVM_sig.Generic_irmin_pvm_context_sig) : S with type context = Context.Tree.t and type state = Context.tree @@ -1587,6 +1587,11 @@ module Make (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : let step_transition ~is_reveal_enabled input_given state = let open Lwt_syntax in + (* Get the current level to include it in the proof. It is needed as the + tick's merkle proof is also used to retrieve the level at which the tick + was executed. If the proof production gets the current level, then proof + verification can get it as well. *) + let* _current_level = get_current_level state in let* request = is_input_state ~is_reveal_enabled state in let error msg = state_of (internal_error msg) state in @@ -1631,6 +1636,18 @@ module Make (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : type error += Arith_proof_verification_failed + let get_proof_state_level proof = + let open Lwt_result_syntax in + let proof = Context.cast_read_only proof in + let*! result = + Context.verify_proof proof (fun state -> + let*! current_level_opt = get_current_level state in + Lwt.return (state, current_level_opt)) + in + match result with + | None -> tzfail Arith_proof_verification_failed + | Some (_state, current_level_opt) -> return current_level_opt + let verify_proof ~is_reveal_enabled input_given proof = let open Lwt_result_syntax in let*! result = @@ -1790,5 +1807,7 @@ module Protocol_implementation = Make (struct let proof_after proof = kinded_hash_to_state_hash proof.Context.Proof.after + let cast_read_only proof = Context.Proof.{proof with after = proof.before} + let proof_encoding = Context.Proof_encoding.V2.Tree2.tree_proof_encoding end) diff --git a/src/proto_alpha/lib_protocol/sc_rollup_arith.mli b/src/proto_alpha/lib_protocol/sc_rollup_arith.mli index aba54e9723aca09e61ebf6bb8af944e931a8cde3..04ff2569dfb5bd0eb3767b5b28592b28c96937f5 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_arith.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_arith.mli @@ -159,7 +159,7 @@ module Protocol_implementation : and type state = Context.tree and type proof = Context.Proof.tree Context.Proof.t -module Make (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : +module Make (Context : Sc_rollup_PVM_sig.Generic_irmin_pvm_context_sig) : S with type context = Context.Tree.t and type state = Context.tree diff --git a/src/proto_alpha/lib_protocol/sc_rollup_game_repr.ml b/src/proto_alpha/lib_protocol/sc_rollup_game_repr.ml index d5dda115c6873aa7f68275a02415c64a8ea2b7bf..b79d30d11f737ff618b380168cb56b23e051467e 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_game_repr.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_game_repr.ml @@ -745,10 +745,9 @@ let check_proof_refute_stop_state ~stop_state input input_request proof = check_proof_stop_state ~stop_state input input_request proof false (** Returns the validity of the first final move on top of a dissection. *) -let validity_final_move ~pvm ~dal_parameters ~dal_activation_level - ~dal_attestation_lag ~dal_number_of_slots ~first_move ~metadata ~proof ~game - ~start_chunk ~stop_chunk ~is_reveal_enabled ~dal_attested_slots_validity_lag - = +let validity_final_move ~pvm ~dal_activation_level ~find_dal_parameters + ~first_move ~metadata ~proof ~game ~start_chunk ~stop_chunk + ~is_reveal_enabled ~dal_attested_slots_validity_lag = let open Lwt_result_syntax in let*! res = let {inbox_snapshot; inbox_level; dal_snapshot; _} = game in @@ -762,10 +761,8 @@ let validity_final_move ~pvm ~dal_parameters ~dal_activation_level inbox_snapshot inbox_level dal_snapshot - dal_parameters + ~find_dal_parameters ~dal_activation_level - ~dal_attestation_lag - ~dal_number_of_slots ~is_reveal_enabled ~dal_attested_slots_validity_lag proof @@ -814,15 +811,12 @@ let validity_final_move ~pvm ~dal_parameters ~dal_activation_level - The proof stop on the state different than the refuted one. - The proof is correctly verified. *) -let validity_first_final_move ~pvm ~dal_parameters ~dal_activation_level - ~dal_attestation_lag ~dal_number_of_slots ~metadata ~proof ~game - ~start_chunk ~stop_chunk = +let validity_first_final_move ~pvm ~find_dal_parameters ~dal_activation_level + ~metadata ~proof ~game ~start_chunk ~stop_chunk = validity_final_move ~pvm - ~dal_parameters ~dal_activation_level - ~dal_attestation_lag - ~dal_number_of_slots + ~find_dal_parameters ~first_move:true ~metadata ~proof @@ -837,15 +831,12 @@ let validity_first_final_move ~pvm ~dal_parameters ~dal_activation_level - The proof stop on the state validates the refuted one. - The proof is correctly verified. *) -let validity_second_final_move ~pvm ~dal_parameters ~dal_activation_level - ~dal_attestation_lag ~dal_number_of_slots ~metadata ~agreed_start_chunk - ~refuted_stop_chunk ~game ~proof = +let validity_second_final_move ~pvm ~dal_activation_level ~find_dal_parameters + ~metadata ~agreed_start_chunk ~refuted_stop_chunk ~game ~proof = validity_final_move ~pvm - ~dal_parameters ~dal_activation_level - ~dal_attestation_lag - ~dal_number_of_slots + ~find_dal_parameters ~first_move:false ~metadata ~proof @@ -902,9 +893,8 @@ let cost_play ~step ~choice = scale10 @@ Gas_limit_repr.atomic_step_cost @@ Michelson_v1_gas_costs.cost_N_IBlake2b overapproximated_hashing_size -let play kind dal_parameters ~dal_activation_level ~dal_attestation_lag - ~dal_number_of_slots ~stakers metadata game ~step ~choice ~is_reveal_enabled - ~dal_attested_slots_validity_lag = +let play kind ~dal_activation_level ~find_dal_parameters ~stakers metadata game + ~step ~choice ~is_reveal_enabled ~dal_attested_slots_validity_lag = let open Lwt_result_syntax in let (Packed ((module PVM) as pvm)) = Sc_rollups.Kind.pvm_of kind in let mk_loser loser = @@ -944,10 +934,8 @@ let play kind dal_parameters ~dal_activation_level ~dal_attestation_lag let*! player_result = validity_first_final_move ~pvm - ~dal_parameters ~dal_activation_level - ~dal_attestation_lag - ~dal_number_of_slots + ~find_dal_parameters ~proof ~metadata ~game @@ -981,10 +969,8 @@ let play kind dal_parameters ~dal_activation_level ~dal_attestation_lag let*! player_result = validity_second_final_move ~pvm - ~dal_parameters ~dal_activation_level - ~dal_attestation_lag - ~dal_number_of_slots + ~find_dal_parameters ~metadata ~agreed_start_chunk ~refuted_stop_chunk diff --git a/src/proto_alpha/lib_protocol/sc_rollup_game_repr.mli b/src/proto_alpha/lib_protocol/sc_rollup_game_repr.mli index 632a7c44b04bfb37291b123d0bff43758c64e267..b20c29c4ba1e05819b91bd25c953a8e3c21898ce 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_game_repr.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_game_repr.mli @@ -390,10 +390,9 @@ val status_encoding : status Data_encoding.t *) val play : Sc_rollups.Kind.t -> - Dal_slot_repr.parameters -> dal_activation_level:Raw_level_repr.t option -> - dal_attestation_lag:int -> - dal_number_of_slots:int -> + find_dal_parameters: + (Raw_level_repr.t -> Constants_parametric_repr.dal tzresult Lwt.t) -> stakers:Index.t -> Sc_rollup_metadata_repr.t -> t -> diff --git a/src/proto_alpha/lib_protocol/sc_rollup_origination_machine.ml b/src/proto_alpha/lib_protocol/sc_rollup_origination_machine.ml index baaf738154cc47c69557ab97d7f8579f7e813eda..c30f902ea62cc775ea015179180beb0f443b689e 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_origination_machine.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_origination_machine.ml @@ -50,6 +50,8 @@ module Context_no_proofs = struct let proof_after = function (_ : proof) -> . + let cast_read_only = function (_ : proof) -> . + let proof_encoding = void end diff --git a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml index 49b4130e1329b427118aaf9aee894b046ca8ca44..e4d7fd1fcc4fecfb2367d64393f54f51a2a2e442 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml @@ -383,9 +383,9 @@ end let valid (type state proof output) ~(pvm : (state, proof, output) Sc_rollups.PVM.implementation) ~metadata - snapshot commit_inbox_level dal_snapshot dal_parameters - ~dal_activation_level ~dal_attestation_lag ~dal_number_of_slots - ~is_reveal_enabled ~dal_attested_slots_validity_lag (proof : proof t) = + snapshot commit_inbox_level dal_snapshot ~find_dal_parameters + ~dal_activation_level ~is_reveal_enabled ~dal_attested_slots_validity_lag + (proof : proof t) = let open Lwt_result_syntax in let (module P) = pvm in let origination_level = metadata.Sc_rollup_metadata_repr.origination_level in @@ -411,33 +411,49 @@ let valid (type state proof output) return_some (Sc_rollup_PVM_sig.Reveal (Raw_data data)) | Some (Reveal_proof Metadata_proof) -> return_some (Sc_rollup_PVM_sig.Reveal (Metadata metadata)) - | Some (Reveal_proof (Dal_page_proof {proof; page_id})) -> + | Some (Reveal_proof (Dal_page_proof {proof = dal_page_proof; page_id})) -> + let* disputed_level = P.get_proof_state_level proof.pvm_step in + let* dal_parameters : Constants_parametric_repr.dal = + find_dal_parameters + ((* The rationale for [Option.value + ~default:metatadata.origination_level] is the first input a + Smart Rollup will consume is the [Start_of_level] of + origination_level + 1. As the level of a PVM is given by the + inputs, if it's none, that means the PVM has never consumed an + input and therefore is on the origination level. *) + Option.value + ~default:metadata.origination_level + disputed_level) + in Dal_helpers.verify - ~dal_number_of_slots + ~dal_number_of_slots:dal_parameters.number_of_slots ~metadata ~dal_activation_level ~dal_attested_slots_validity_lag - dal_parameters + dal_parameters.cryptobox_parameters ~commit_inbox_level page_id dal_snapshot - proof + dal_page_proof |> Lwt.return | Some (Reveal_proof Dal_parameters_proof) -> - (* FIXME: https://gitlab.com/tezos/tezos/-/issues/6562 - Support revealing historical DAL parameters. - - Currently, we do not support revealing DAL parameters for the past. - We ignore the given [published_level] and use the DAL parameters. *) + let* disputed_level = P.get_proof_state_level proof.pvm_step in + let* dal_parameters = + find_dal_parameters + (Option.value ~default:metadata.origination_level disputed_level) + in return_some (Sc_rollup_PVM_sig.Reveal (Dal_parameters Sc_rollup_dal_parameters_repr. { - number_of_slots = Int64.of_int dal_number_of_slots; - attestation_lag = Int64.of_int dal_attestation_lag; - slot_size = Int64.of_int dal_parameters.slot_size; - page_size = Int64.of_int dal_parameters.page_size; + number_of_slots = Int64.of_int dal_parameters.number_of_slots; + attestation_lag = + Int64.of_int dal_parameters.attestation_lag; + slot_size = + Int64.of_int dal_parameters.cryptobox_parameters.slot_size; + page_size = + Int64.of_int dal_parameters.cryptobox_parameters.page_size; })) in let input = @@ -548,7 +564,8 @@ module type PVM_with_context_and_state = sig end end -let produce ~metadata pvm_and_state commit_inbox_level ~is_reveal_enabled = +let produce ~metadata ~find_dal_parameters pvm_and_state commit_inbox_level + ~is_reveal_enabled = let open Lwt_result_syntax in let (module P : PVM_with_context_and_state) = pvm_and_state in let open P in @@ -647,20 +664,29 @@ let produce ~metadata pvm_and_state commit_inbox_level ~is_reveal_enabled = ~dal_attested_slots_validity_lag confirmed_slots_history | Needs_reveal Reveal_dal_parameters -> - let open Dal_with_history in + let*! level = P.get_current_level P.state in + let level = Option.value ~default:metadata.origination_level level in + let* dal_parameters : Constants_parametric_repr.dal = + find_dal_parameters level + in return ( Some (Reveal_proof Dal_parameters_proof), Some - Sc_rollup_PVM_sig.( - Reveal - (Dal_parameters - Sc_rollup_dal_parameters_repr. - { - number_of_slots = Int64.of_int dal_number_of_slots; - attestation_lag = Int64.of_int dal_attestation_lag; - slot_size = Int64.of_int dal_parameters.slot_size; - page_size = Int64.of_int dal_parameters.page_size; - })) ) + (Sc_rollup_PVM_sig.Reveal + (Dal_parameters + Sc_rollup_dal_parameters_repr. + { + number_of_slots = + Int64.of_int dal_parameters.number_of_slots; + attestation_lag = + Int64.of_int dal_parameters.attestation_lag; + slot_size = + Int64.of_int + dal_parameters.cryptobox_parameters.slot_size; + page_size = + Int64.of_int + dal_parameters.cryptobox_parameters.page_size; + })) ) in let input_given = Option.bind diff --git a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.mli b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.mli index cc9d3b64a148187771ee77b4984b52ee967be482..97fbbd0322da827d7a8af1e3b94c5a04ba19f299 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.mli @@ -168,10 +168,9 @@ val valid : Sc_rollup_inbox_repr.history_proof -> Raw_level_repr.t -> Dal_slot_repr.History.t -> - Dal_slot_repr.parameters -> + find_dal_parameters: + (Raw_level_repr.t -> Constants_parametric_repr.dal tzresult Lwt.t) -> dal_activation_level:Raw_level_repr.t option -> - dal_attestation_lag:int -> - dal_number_of_slots:int -> is_reveal_enabled:Sc_rollup_PVM_sig.is_reveal_enabled -> dal_attested_slots_validity_lag:int -> 'proof t -> @@ -244,7 +243,7 @@ module type PVM_with_context_and_state = sig end end -(** [produce ~metadata pvm_and_state inbox_context inbox_history +(** [produce ~metadata ~find_dal_parameters pvm_and_state inbox_context inbox_history commit_inbox_level] will construct a full refutation game proof out of the [state] given in [pvm_and_state]. It uses the [inbox] if necessary to provide input in the proof. If the input is above or at [commit_level] it @@ -267,6 +266,8 @@ end *) val produce : metadata:Sc_rollup_metadata_repr.t -> + find_dal_parameters: + (Raw_level_repr.t -> Constants_parametric_repr.dal tzresult Lwt.t) -> (module PVM_with_context_and_state) -> Raw_level_repr.t -> is_reveal_enabled:Sc_rollup_PVM_sig.is_reveal_enabled -> diff --git a/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml b/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml index 1a10345461af8a1a46032512ee4150fa384d0079..c36e9133ae92c5df8356523b559e509a234c28fe 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml @@ -466,10 +466,8 @@ let game_move ctxt rollup ~player ~opponent ~step ~choice = let* move_result = Sc_rollup_game_repr.play kind - dal.cryptobox_parameters ~dal_activation_level - ~dal_attestation_lag:dal.attestation_lag - ~dal_number_of_slots:dal.number_of_slots + ~find_dal_parameters:(Dal_storage.parameters ctxt) ~stakers metadata game diff --git a/src/proto_alpha/lib_protocol/sc_rollup_riscv.ml b/src/proto_alpha/lib_protocol/sc_rollup_riscv.ml index f80fdc10462c4eb45c8f574b6f34a85b414c47e8..04868bf6392a52d0ddcb90569837a3a444c48bff 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_riscv.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_riscv.ml @@ -133,6 +133,13 @@ module Protocol_implementation : let install_boot_sector state boot_sector = Riscv.install_boot_sector state boot_sector + let get_proof_state_level _proof = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/8148 + + Returns the level included in the proof, that is the level where the + disputed tick was processed. *) + Lwt_result_syntax.return_none + let verify_proof ~is_reveal_enabled:_ input proof = let open Lwt_result_syntax in let* input_request = diff --git a/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml b/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml index c9e03c9dad4298826bbe303a93507914928ca24d..37b7705496b6ea82bd75a257be0bc2a76e1cb505 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml @@ -170,7 +170,7 @@ module V2_0_0 = struct *) module Make (Make_backend : Make_wasm) - (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : + (Context : Sc_rollup_PVM_sig.Generic_irmin_pvm_context_sig) : S with type context = Context.Tree.t and type state = Context.tree @@ -409,8 +409,18 @@ module V2_0_0 = struct let eval state = state_of eval_step state + let get_current_level state = + let open Lwt_syntax in + let+ res = result_of get_last_message_read state in + Option.map fst res + let step_transition ~is_reveal_enabled input_given state = let open Lwt_syntax in + (* Get the current level to include it in the proof. It is needed as the + tick's merkle proof is also used to retrieve the level at which the tick + was executed. If the proof production gets the the current level, then + then proof verification can get it as well. *) + let* _current_level = get_current_level state in let* request = is_input_state ~is_reveal_enabled state in let* state = match request with @@ -422,6 +432,18 @@ module V2_0_0 = struct in return (state, request) + let get_proof_state_level proof = + let open Lwt_result_syntax in + let proof = Context.cast_read_only proof in + let*! result = + Context.verify_proof proof (fun state -> + let*! current_level_opt = get_current_level state in + Lwt.return (state, current_level_opt)) + in + match result with + | None -> tzfail WASM_proof_verification_failed + | Some (_state, current_level_opt) -> return current_level_opt + let verify_proof ~is_reveal_enabled input_given proof = let open Lwt_result_syntax in let*! result = @@ -635,10 +657,7 @@ module V2_0_0 = struct dissection) WASM_invalid_dissection_distribution - let get_current_level state = - let open Lwt_syntax in - let+ res = result_of get_last_message_read state in - Option.map fst res + let get_current_level = get_current_level module Internal_for_tests = struct let insert_failure state = @@ -690,6 +709,9 @@ module V2_0_0 = struct let proof_after proof = kinded_hash_to_state_hash proof.Context.Proof.after + let cast_read_only proof = + Context.Proof.{proof with after = proof.before} + let proof_encoding = Context.Proof_encoding.V2.Tree2.tree_proof_encoding end) end diff --git a/src/proto_alpha/lib_protocol/sc_rollup_wasm.mli b/src/proto_alpha/lib_protocol/sc_rollup_wasm.mli index 818da8195857be216f64b958d8a18a5ceb407bcc..51fbefbf8b63d1740ba3ac01856b3b1ad5d9673b 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_wasm.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_wasm.mli @@ -69,7 +69,7 @@ module V2_0_0 : sig (** Build a WebAssembly PVM using the given proof-supporting context. *) module Make (Lib_scoru_Wasm : Make_wasm) - (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : + (Context : Sc_rollup_PVM_sig.Generic_irmin_pvm_context_sig) : S with type context = Context.Tree.t and type state = Context.tree diff --git a/src/proto_alpha/lib_protocol/test/helpers/sc_rollup_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/sc_rollup_helpers.ml index d0b53961f95006efbe6e6249c4fef4affa41dc72..997e594cebfbcd0627a09cfcae64b7855b0fe1fd 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/sc_rollup_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/sc_rollup_helpers.ml @@ -88,6 +88,8 @@ struct let proof_after proof = kinded_hash_to_state_hash proof.Context.Proof.after + let cast_read_only proof = Context.Proof.{proof with after = proof.before} + let proof_encoding = Tezos_context_merkle_proof_encoding.Merkle_proof_encoding.V2.Tree2 .tree_proof_encoding diff --git a/src/proto_alpha/lib_protocol/test/pbt/test_refutation_game.ml b/src/proto_alpha/lib_protocol/test/pbt/test_refutation_game.ml index 84f179d0595389697c952491a98a93f357beda36..4b434978aa5f54738deffdc20cbe03ffb3f89648 100644 --- a/src/proto_alpha/lib_protocol/test/pbt/test_refutation_game.ml +++ b/src/proto_alpha/lib_protocol/test/pbt/test_refutation_game.ml @@ -1175,6 +1175,7 @@ let build_proof ~player_client start_tick (game : Game.t) = let*! proof = Sc_rollup.Proof.produce ~metadata + ~find_dal_parameters:(fun _ -> assert false) pvm_with_context_and_state game.inbox_level ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default diff --git a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_arith.ml b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_arith.ml index 84c496bd1c6e43dc533204f3092fa587a38663dc..c604a5bf3ada8f18efb4a30fe8df38e3919b23ea 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_arith.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_arith.ml @@ -76,6 +76,9 @@ module Arith_Context = struct let proof_after proof = kinded_hash_to_state_hash proof.Context_binary.Proof.after + let cast_read_only proof = + Context_binary.Proof.{proof with after = proof.before} + let produce_proof context tree step = let open Lwt_syntax in (* FIXME: With on-disk context, we cannot commit the empty @@ -673,7 +676,6 @@ let test_serialized_reveal_proof ~hashed_preimage ~input_preimage () = let snapshot = Sc_rollup.Inbox.take_snapshot inbox.inbox in let dal_snapshot = Dal.Slots_history.genesis in let constants = Default_parameters.constants_mainnet in - let dal_parameters = constants.dal in let dal_activation_level = if constants.dal.feature_enable then Some constants.sc_rollup.reveal_activation_level.dal_parameters @@ -715,6 +717,10 @@ let test_serialized_reveal_proof ~hashed_preimage ~input_preimage () = let*@ proof = Sc_rollup.Proof.produce ~metadata + ~find_dal_parameters:(fun _ -> + (* The proof doesn't include a DAL step so finding the parameters is in + practice not used. *) + assert false) pvm_with_context_and_state Raw_level.root ~is_reveal_enabled @@ -730,11 +736,12 @@ let test_serialized_reveal_proof ~hashed_preimage ~input_preimage () = snapshot Raw_level.root dal_snapshot - dal_parameters.cryptobox_parameters ~dal_activation_level ~dal_attested_slots_validity_lag - ~dal_attestation_lag:dal_parameters.attestation_lag - ~dal_number_of_slots:dal_parameters.number_of_slots + ~find_dal_parameters:(fun _ -> + (* The proof doesn't include a DAL step so finding the parameters is in + practice not used. *) + assert false) ~is_reveal_enabled {proof with pvm_step} diff --git a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_game.ml b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_game.ml index f59e2b4f17aad77503a030c9071a8c54bfb70d5d..5df3af9e46b78295e39e1f2cae6153790daa11f2 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_game.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_game.ml @@ -243,7 +243,6 @@ let test_invalid_serialized_inbox_proof () = let snapshot = Sc_rollup.Inbox.take_snapshot inbox in let dal_snapshot = Dal.Slots_history.genesis in let constants = Default_parameters.constants_mainnet in - let dal_parameters = constants.dal in let dal_activation_level = if constants.dal.feature_enable then Some constants.sc_rollup.reveal_activation_level.dal_parameters @@ -283,11 +282,12 @@ let test_invalid_serialized_inbox_proof () = snapshot Raw_level.root dal_snapshot - dal_parameters.cryptobox_parameters ~dal_activation_level ~dal_attested_slots_validity_lag - ~dal_attestation_lag:dal_parameters.attestation_lag - ~dal_number_of_slots:dal_parameters.number_of_slots + ~find_dal_parameters:(fun _ -> + (* The proof doesn't include a DAL step so finding the parameters is in + practice not used. *) + assert false) ~is_reveal_enabled proof in diff --git a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_wasm.ml b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_wasm.ml index 6016af27310aab2db8e0ddb92033055606dea605..f37aff3380ed2995856dae49ad0edd7f5d2003ab 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_wasm.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_wasm.ml @@ -83,6 +83,8 @@ module Wasm_context = struct let proof_after proof = kinded_hash_to_state_hash proof.Context.Proof.after + let cast_read_only proof = Context.Proof.{proof with after = proof.before} + let proof_encoding = Proof_encoding.V2.Tree2.tree_proof_encoding end diff --git a/src/proto_alpha/lib_sc_rollup/context_helpers.ml b/src/proto_alpha/lib_sc_rollup/context_helpers.ml index 87afcbbb22fd9e25bf84b8db142d5a7930526651..ede3ed4642a9e6dbcbd1717b0c2f2308b1826863 100644 --- a/src/proto_alpha/lib_sc_rollup/context_helpers.ml +++ b/src/proto_alpha/lib_sc_rollup/context_helpers.ml @@ -69,6 +69,9 @@ module In_memory = struct let proof_after proof = kinded_hash_to_state_hash proof.Context_binary.Proof.after + let cast_read_only proof = + Context_binary.Proof.{proof with after = proof.before} + let proof_encoding = Tezos_context_merkle_proof_encoding.Merkle_proof_encoding.V2.Tree2 .tree_proof_encoding diff --git a/src/proto_alpha/lib_sc_rollup/context_helpers.mli b/src/proto_alpha/lib_sc_rollup/context_helpers.mli index d389c4a6f664ca7888029aefdb0a16dd33d9f90c..bd7c9dafdc65b895210a2098ac04e72f86c2b715 100644 --- a/src/proto_alpha/lib_sc_rollup/context_helpers.mli +++ b/src/proto_alpha/lib_sc_rollup/context_helpers.mli @@ -26,9 +26,9 @@ open Protocol.Alpha_context (** [In_memory] is a context that can be used to instantiate an Arith or Wasm PVM. It's signature is - {!Protocol.Alpha_context.Sc_rollup.Generic_pvm_context_sig} *) + {!Protocol.Alpha_context.Sc_rollup.Generic_irmin_pvm_context_sig} *) module In_memory : - Sc_rollup.Generic_pvm_context_sig + Sc_rollup.Generic_irmin_pvm_context_sig with type Tree.tree = Tezos_context_memory.Context_binary.tree and type Tree.t = Tezos_context_memory.Context_binary.t and type proof = diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.ml index 24ed9d920035a1ff83dd357da0a9fb044ac7d006..38a3bf4f45cb686e7729e8cae12b5ca2c0cf9fd2 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.ml +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.ml @@ -254,6 +254,31 @@ let generate_proof (node_ctxt : _ Node_context.t) supported in protocols <= 18. *) fun ~current_block_level:_ _ -> true in + + let find_dal_parameters level = + Environment.Error_monad.catch_s (fun () -> + let open Lwt_syntax in + let* shell_result = + Plugin.RPC.Dal.past_parameters + (new Protocol_client_context.wrap_full node_ctxt.cctxt) + (node_ctxt.cctxt#chain, `Head 0) + level + in + (* Convert [shell_tzresult] to protocol's [tzresult]. + Note that this is the opposite direction than the one provided by + `Environment.wrap_tzresult`. *) + match shell_result with + | Ok dal_params -> Lwt.return dal_params + | Error err -> + Lwt.fail + (Failure + (Format.asprintf + "Failed to retrieve DAL parameters for level %a: %a" + Raw_level.pp + level + pp_print_trace + err))) + in let* proof = trace (Sc_rollup_node_errors.Cannot_produce_proof @@ -264,6 +289,7 @@ let generate_proof (node_ctxt : _ Node_context.t) @@ let*! result = Sc_rollup.Proof.produce ~metadata + ~find_dal_parameters (module P) (Raw_level.of_int32_exn game.inbox_level) ~is_reveal_enabled @@ -281,10 +307,8 @@ let generate_proof (node_ctxt : _ Node_context.t) snapshot (Raw_level.of_int32_exn game.inbox_level) dal_slots_history - dal_parameters ~dal_activation_level - ~dal_attestation_lag - ~dal_number_of_slots + ~find_dal_parameters ~pvm:(module PVM) unserialized_proof ~is_reveal_enabled diff --git a/src/proto_alpha/lib_sc_rollup_node/riscv_pvm.ml b/src/proto_alpha/lib_sc_rollup_node/riscv_pvm.ml index 2f3b9872c9e2584dbe17a5f386d0b0960312a47c..d11ba8b7966deefe66ec98bae1513b6bfa6f7993 100644 --- a/src/proto_alpha/lib_sc_rollup_node/riscv_pvm.ml +++ b/src/proto_alpha/lib_sc_rollup_node/riscv_pvm.ml @@ -129,6 +129,13 @@ module PVM : let eval state = Backend.compute_step state + let get_proof_state_level _proof = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/8148 + + Returns the level included in the proof, that is the level where the + disputed tick was processed. *) + Lwt_result_syntax.return_none + let verify_proof ~is_reveal_enabled:_ input_given proof = let open Environment.Error_monad.Lwt_result_syntax in let* input_request = diff --git a/tezt/tests/sc_rollup_migration.ml b/tezt/tests/sc_rollup_migration.ml index d7b2edb6170f850cb79a764ef700c8b49c15f340..5b076c9fd97cda955959859291d4209cffa455fe 100644 --- a/tezt/tests/sc_rollup_migration.ml +++ b/tezt/tests/sc_rollup_migration.ml @@ -946,12 +946,12 @@ let test_l2_migration_scenario_event ?parameters_ty scenario migrate_from rollup_node sc_rollup tezos_node tezos_client let test_refutation_migration_scenario ?(flaky = false) ?commitment_period - ?challenge_window ~variant ~mode ~kind scenario ~migrate_from ~migrate_to - ~migration_on_event = + ?challenge_window ~variant ~mode ~kind ?boot_sector ?(extra_tags = []) + scenario ~migrate_from ~migrate_to ~migration_on_event = let tags = (if flaky then [Tag.flaky] else []) @ ["refutation"] - @ if mode = Sc_rollup_node.Accuser then ["accuser"] else [] + @ if mode = Sc_rollup_node.Accuser then ["accuser"] else [] @ extra_tags in let variant = variant ^ if mode = Accuser then "+accuser" else "" in @@ -964,6 +964,7 @@ let test_refutation_migration_scenario ?(flaky = false) ?commitment_period ~rollup_node_name:"honest" ~tags ~variant + ?boot_sector ~description:"refutation games over migrations" ~migrate_from ~migrate_to @@ -1026,6 +1027,52 @@ let test_refutation_migration ~migrate_from ~migrate_to = ]) tests +let test_refutation_migration_dal_parameters ~migrate_from ~migrate_to = + if Protocol.(number migrate_to >= 25) then + let from_params = Protocol.parameter_file migrate_from |> JSON.parse_file in + let to_params = Protocol.parameter_file migrate_to |> JSON.parse_file in + let reveal_dal_params params = + let number_of_slots = + JSON.(params |-> "dal_parametric" |-> "number_of_slots" |> as_int) + in + let attestation_lag = + JSON.(params |-> "dal_parametric" |-> "attestation_lag" |> as_int) + in + let slot_size = + JSON.(params |-> "dal_parametric" |-> "slot_size" |> as_int) + in + let page_size = + JSON.(params |-> "dal_parametric" |-> "page_size" |> as_int) + in + (number_of_slots, attestation_lag, slot_size, page_size) + in + let from_dal_params = reveal_dal_params from_params in + let to_dal_params = reveal_dal_params to_params in + if from_dal_params <> to_dal_params then + let p1, p2, p3, p4 = to_dal_params in + let loser_mode = sf "reveal_dal_parameters %d %d %d %d" p1 p2 p3 p4 in + (* We play a refutation game where the malicious rollup node plays the DAL + parameters of protocol P for commitments in protocol P-1. The refutation + game is played in protocol P, therefore, if the refutation game cannot + handle older parameters, malicious rollup node will not lose. *) + let kernel = Constant.WASM.echo_dal_reveal_parameters in + test_refutation_migration_scenario + ~kind:"wasm_2_0_0" + ~mode:Operator + ~challenge_window:10 + ~commitment_period:5 + ~variant:"reveal_dal_parameters" + ~boot_sector:(read_kernel ~base:"" ~suffix:"" @@ Uses.path kernel) + ~extra_tags:[Uses.tag kernel] + (refutation_scenario_parameters + ~loser_modes:[loser_mode] + (inputs_for 10) + ~final_level:50 + ~priority:`Priority_honest) + ~migrate_from + ~migrate_to + ~migration_on_event:(commitment_computed_event ~inbox_level:5) + let register_migration ~kind ~migrate_from ~migrate_to = test_migration_inbox ~kind ~migrate_from ~migrate_to ; test_migration_ticket_inbox ~kind ~migrate_from ~migrate_to ; @@ -1040,7 +1087,8 @@ let register_migration ~kind ~migrate_from ~migrate_to = test_migration_removes_dead_games ~kind ~migrate_from ~migrate_to let register_migration_only_wasm ~migrate_from ~migrate_to = - test_refutation_migration ~migrate_from ~migrate_to + test_refutation_migration ~migrate_from ~migrate_to ; + test_refutation_migration_dal_parameters ~migrate_from ~migrate_to let register ~migrate_from ~migrate_to = register_migration ~kind:"arith" ~migrate_from ~migrate_to ;