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 3c7c9d315a9808335dc83db94ee0c17b739d934f..e63e7862b5d8d573359950e9b288217417eaeecd 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml @@ -24,6 +24,31 @@ (* *) (*****************************************************************************) +type error += Sc_rollup_proof_check of string + +type error += Sc_rollup_invalid_serialized_inbox_proof + +let () = + register_error_kind + `Permanent + ~id:"Sc_rollup_proof_check" + ~title:"Invalid proof" + ~description:"An invalid proof has been submitted" + ~pp:(fun fmt msg -> Format.fprintf fmt "Invalid proof: %s" msg) + Data_encoding.(obj1 @@ req "reason" string) + (function Sc_rollup_proof_check msg -> Some msg | _ -> None) + (fun msg -> Sc_rollup_proof_check msg) ; + + register_error_kind + `Permanent + ~id:"Sc_rollup_invalid_serialized_inbox_proof" + ~title:"Invalid serialized inbox proof" + ~description:"The serialized inbox proof can not be de-serialized" + ~pp:(fun fmt () -> Format.fprintf fmt "Invalid serialized inbox proof") + Data_encoding.unit + (function Sc_rollup_invalid_serialized_inbox_proof -> Some () | _ -> None) + (fun () -> Sc_rollup_invalid_serialized_inbox_proof) + type t = { pvm_step : Sc_rollups.wrapped_proof; inbox : Sc_rollup_inbox_repr.serialized_proof option; @@ -59,19 +84,6 @@ let cut_at_level level input = let input_level = Sc_rollup_PVM_sem.(input.inbox_level) in if Raw_level_repr.(level <= input_level) then None else Some input -type error += Sc_rollup_proof_check of string - -let () = - register_error_kind - `Permanent - ~id:"Sc_rollup_proof_check" - ~title:"Invalid proof" - ~description:"An invalid proof has been submitted" - ~pp:(fun fmt msg -> Format.fprintf fmt "Invalid proof: %s" msg) - Data_encoding.(obj1 @@ req "reason" string) - (function Sc_rollup_proof_check msg -> Some msg | _ -> None) - (fun msg -> Sc_rollup_proof_check msg) - let proof_error reason = let open Lwt_tzresult_syntax in fail (Sc_rollup_proof_check reason) @@ -82,7 +94,7 @@ let check p reason = let check_inbox_proof snapshot serialized_inbox_proof (level, counter) = match Sc_rollup_inbox_repr.of_serialized_proof serialized_inbox_proof with - | None -> return None + | None -> fail Sc_rollup_invalid_serialized_inbox_proof | Some inbox_proof -> Sc_rollup_inbox_repr.verify_proof (level, counter) snapshot inbox_proof 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 81efa00c44362ba2a517b99a66a644d71dcf0d25..cf237cc62de1d56282641bdef8b6961f58c99325 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.mli @@ -64,6 +64,8 @@ type t = { type error += Sc_rollup_proof_check of string +type error += Sc_rollup_invalid_serialized_inbox_proof + val encoding : t Data_encoding.t val pp : Format.formatter -> t -> unit 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 55a6005e4ac62e897b6c729c28cfd06723190b8f..00f50d5171a2b96ca4a65aa4541088138ace4289 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 @@ -306,6 +306,48 @@ let test_staker_injectivity () = res (( = ) (Sc_rollup_errors.Sc_rollup_staker_in_game (`Defender defender))) +module Arith_pvm = Sc_rollup_helpers.Arith_pvm + +(** Test that sending a invalid serialized inbox proof to + {Sc_rollup_proof_repr.valid} is rejected. *) +let test_invalid_serialized_inbox_proof () = + let open Lwt_result_syntax in + let open Alpha_context in + let* ctxt = Test_sc_rollup_inbox.create_context () in + let*! inbox = + Sc_rollup.Inbox.empty ctxt Sc_rollup.Address.zero Raw_level.root + in + let snapshot = Sc_rollup.Inbox.take_snapshot inbox in + + let ctxt = Tezos_context_memory.make_empty_context () in + let*! state = Arith_pvm.initial_state ctxt in + (* We evaluate the boot sector, so the [input_requested] is a + [First_after]. *) + let*! state = Arith_pvm.eval state in + let*! proof = Arith_pvm.produce_proof ctxt None state in + let proof = WithExceptions.Result.get_ok ~loc:__LOC__ proof in + let wrapped_proof = + Sc_rollup.Arith_pvm_with_proof + (module struct + include Arith_pvm + + let proof = proof + end) + in + + (* We create an obviously invalid inbox *) + let inbox = Bytes.of_string "I am the big bad wolf" |> Obj.magic in + let proof = Sc_rollup.Proof.{pvm_step = wrapped_proof; inbox = Some inbox} in + + let*! res = + T.lift + @@ Sc_rollup.Proof.valid snapshot Raw_level.root ~pvm_name:"arith" proof + in + Assert.proto_error + ~loc:__LOC__ + res + (( = ) Sc_rollup_proof_repr.Sc_rollup_invalid_serialized_inbox_proof) + let tests = [ Tztest.tztest @@ -320,4 +362,8 @@ let tests = "Staker can be in at most one game (injectivity)." `Quick test_staker_injectivity; + Tztest.tztest + "Invalid serialized inbox proof is rejected." + `Quick + test_invalid_serialized_inbox_proof; ]