diff --git a/src/proto_alpha/lib_client/mockup.ml b/src/proto_alpha/lib_client/mockup.ml index e3921af0d8d322da2830065add894d25a09b24a1..95ad990af956e47118024eb0545163df163d5801 100644 --- a/src/proto_alpha/lib_client/mockup.ml +++ b/src/proto_alpha/lib_client/mockup.ml @@ -84,6 +84,7 @@ module Protocol_constants_overrides = struct tx_rollup_max_finalized_levels : int option; sc_rollup_enable : bool option; sc_rollup_origination_size : int option; + sc_rollup_challenge_window_in_blocks : int option; (* Additional, "bastard" parameters (they are not protocol constants but partially treated the same way). *) chain_id : Chain_id.t option; timestamp : Time.Protocol.t option; @@ -143,8 +144,9 @@ module Protocol_constants_overrides = struct c.tx_rollup_withdraw_period, c.tx_rollup_max_messages_per_inbox, c.tx_rollup_max_finalized_levels ), - (c.sc_rollup_enable, c.sc_rollup_origination_size) ) ) ) ) - ) )) + ( c.sc_rollup_enable, + c.sc_rollup_origination_size, + c.sc_rollup_challenge_window_in_blocks ) ) ) ) ) ) )) (fun ( ( preserved_cycles, blocks_per_cycle, blocks_per_commitment, @@ -193,8 +195,9 @@ module Protocol_constants_overrides = struct tx_rollup_withdraw_period, tx_rollup_max_messages_per_inbox, tx_rollup_max_finalized_levels ), - (sc_rollup_enable, sc_rollup_origination_size) ) ) ) ) ) - ) -> + ( sc_rollup_enable, + sc_rollup_origination_size, + sc_rollup_challenge_window_in_blocks ) ) ) ) ) ) ) -> { preserved_cycles; blocks_per_cycle; @@ -243,6 +246,7 @@ module Protocol_constants_overrides = struct tx_rollup_max_finalized_levels; sc_rollup_enable; sc_rollup_origination_size; + sc_rollup_challenge_window_in_blocks; chain_id; timestamp; initial_seed; @@ -311,9 +315,10 @@ module Protocol_constants_overrides = struct (opt "tx_rollup_withdraw_period" int31) (opt "tx_rollup_max_messages_per_inbox" int31) (opt "tx_rollup_max_finalized_levels" int31)) - (obj2 + (obj3 (opt "sc_rollup_enable" bool) - (opt "sc_rollup_origination_size" int31)))))))) + (opt "sc_rollup_origination_size" int31) + (opt "sc_rollup_challenge_window_in_blocks" int31)))))))) let default_value (cctxt : Tezos_client_base.Client_context.full) : t tzresult Lwt.t = @@ -393,6 +398,8 @@ module Protocol_constants_overrides = struct Some parametric.tx_rollup_max_finalized_levels; sc_rollup_enable = Some parametric.sc_rollup_enable; sc_rollup_origination_size = Some parametric.sc_rollup_origination_size; + sc_rollup_challenge_window_in_blocks = + Some parametric.sc_rollup_challenge_window_in_blocks; (* Bastard additional parameters. *) chain_id = to_chain_id_opt cpctxt#chain; timestamp = Some header.timestamp; @@ -450,6 +457,7 @@ module Protocol_constants_overrides = struct tx_rollup_max_finalized_levels = None; sc_rollup_enable = None; sc_rollup_origination_size = None; + sc_rollup_challenge_window_in_blocks = None; chain_id = None; timestamp = None; initial_seed = None; @@ -675,6 +683,12 @@ module Protocol_constants_overrides = struct override_value = o.sc_rollup_origination_size; pp = pp_print_int; }; + O + { + name = "sc_rollup_challenge_window_in_blocks"; + override_value = o.sc_rollup_challenge_window_in_blocks; + pp = pp_print_int; + }; O {name = "chain_id"; override_value = o.chain_id; pp = Chain_id.pp}; O { @@ -886,6 +900,10 @@ module Protocol_constants_overrides = struct Option.value ~default:c.sc_rollup_origination_size o.sc_rollup_origination_size; + sc_rollup_challenge_window_in_blocks = + Option.value + ~default:c.sc_rollup_challenge_window_in_blocks + o.sc_rollup_challenge_window_in_blocks; } : Constants.parametric) end diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index a14f707275151a0d4808173560ff44b79135a3ed..2cfb9e9a30ad693d76d525080ab89fdf4d1b66e4 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -118,6 +118,8 @@ let constants_mainnet = sc_rollup_enable = false; (* The following value is chosen to prevent spam. *) sc_rollup_origination_size = 6_314; + (* The challenge window is about a week with 30s block-time (604800s / 30s). *) + sc_rollup_challenge_window_in_blocks = 20_160; } let constants_sandbox = diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index ad628f4074643a1829d07e878baece274f7cca91..d5ce87a64ef9a5f5610c160b39d2ee762309a75a 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -3,6 +3,7 @@ (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) (* Copyright (c) 2019-2022 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -500,3 +501,7 @@ end module Token = Token module Cache = Cache_repr + +module Internal_for_tests = struct + let to_raw x = x +end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 2120ebb79a047e69087e6c8b4ddbf197cb118514..d835143d46b8359b76b959ffca8d8fe222694a76 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -802,6 +802,7 @@ module Constants : sig tx_rollup_max_finalized_levels : int; sc_rollup_enable : bool; sc_rollup_origination_size : int; + sc_rollup_challenge_window_in_blocks : int; } module Generated : sig @@ -1010,6 +1011,10 @@ module Global_constants_storage : sig end end +module Internal_for_tests : sig + val to_raw : context -> Raw_context.t +end + module Cache : sig type size = int @@ -1799,6 +1804,31 @@ module Sc_rollup : sig val encoding : t Data_encoding.t end + module Staker : + S.SIGNATURE_PUBLIC_KEY_HASH with type t = Signature.Public_key_hash.t + + module Commitment_hash : S.HASH + + module State_hash : S.HASH + + module Number_of_messages : Bounded.Int32.S + + module Number_of_ticks : Bounded.Int32.S + + module Commitment : sig + type t = { + compressed_state : State_hash.t; + inbox_level : Raw_level_repr.t; + predecessor : Commitment_hash.t; + number_of_messages : Number_of_messages.t; + number_of_ticks : Number_of_ticks.t; + } + + val encoding : t Data_encoding.t + + val hash : t -> Commitment_hash.t + end + val originate : context -> kind:Kind.t -> @@ -1821,6 +1851,35 @@ module Sc_rollup : sig context -> t -> string list -> (Inbox.t * Z.t * context) tzresult Lwt.t val inbox : context -> t -> (Inbox.t * context) tzresult Lwt.t + + val deposit_stake : context -> t -> Staker.t -> context tzresult Lwt.t + + val withdraw_stake : context -> t -> Staker.t -> context tzresult Lwt.t + + val refine_stake : + context -> + t -> + Raw_level.t -> + Staker.t -> + Commitment.t -> + (Commitment_hash.t * context) tzresult Lwt.t + + val cement_commitment : + context -> t -> Raw_level.t -> Commitment_hash.t -> context tzresult Lwt.t + + type conflict_point = Commitment_hash.t * Commitment_hash.t + + val get_conflict_point : + context -> + t -> + Staker.t -> + Staker.t -> + (conflict_point * context) tzresult Lwt.t + + val get_commitment : + context -> t -> Commitment_hash.t -> (Commitment.t * context) tzresult Lwt.t + + val remove_staker : context -> t -> Staker.t -> context tzresult Lwt.t end module Block_payload : sig diff --git a/src/proto_alpha/lib_protocol/constants_repr.ml b/src/proto_alpha/lib_protocol/constants_repr.ml index 3991648039f1c4bf45e0a0169f4b3c28d435d607..553295189e0feab9e2f331da13526b6a280ab425 100644 --- a/src/proto_alpha/lib_protocol/constants_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_repr.ml @@ -3,7 +3,7 @@ (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) (* Copyright (c) 2020-2021 Nomadic Labs *) -(* Copyright (c) 2022 Trili Tech *) +(* Copyright (c) 2021-2022 Trili Tech, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -171,6 +171,7 @@ type parametric = { tx_rollup_max_finalized_levels : int; sc_rollup_enable : bool; sc_rollup_origination_size : int; + sc_rollup_challenge_window_in_blocks : int; } let parametric_encoding = @@ -223,8 +224,9 @@ let parametric_encoding = c.tx_rollup_max_unfinalized_levels, c.tx_rollup_max_messages_per_inbox, c.tx_rollup_max_finalized_levels ), - (c.sc_rollup_enable, c.sc_rollup_origination_size) ) ) ) ) ) - )) + ( c.sc_rollup_enable, + c.sc_rollup_origination_size, + c.sc_rollup_challenge_window_in_blocks ) ) ) ) ) ) )) (fun ( ( preserved_cycles, blocks_per_cycle, blocks_per_commitment, @@ -271,7 +273,9 @@ let parametric_encoding = tx_rollup_max_unfinalized_levels, tx_rollup_max_messages_per_inbox, tx_rollup_max_finalized_levels ), - (sc_rollup_enable, sc_rollup_origination_size) ) ) ) ) ) ) -> + ( sc_rollup_enable, + sc_rollup_origination_size, + sc_rollup_challenge_window_in_blocks ) ) ) ) ) ) ) -> { preserved_cycles; blocks_per_cycle; @@ -321,6 +325,7 @@ let parametric_encoding = tx_rollup_max_finalized_levels; sc_rollup_enable; sc_rollup_origination_size; + sc_rollup_challenge_window_in_blocks; }) (merge_objs (obj9 @@ -386,9 +391,10 @@ let parametric_encoding = (req "tx_rollup_max_unfinalized_levels" int31) (req "tx_rollup_max_messages_per_inbox" int31) (req "tx_rollup_max_finalized_levels" int31)) - (obj2 + (obj3 (req "sc_rollup_enable" bool) - (req "sc_rollup_origination_size" int31)))))))) + (req "sc_rollup_origination_size" int31) + (req "sc_rollup_challenge_window_in_blocks" int31)))))))) type t = {fixed : fixed; parametric : parametric} diff --git a/src/proto_alpha/lib_protocol/constants_repr.mli b/src/proto_alpha/lib_protocol/constants_repr.mli index f8f951265313e7d046f1375ef863c0ae16fc6d5f..f25928f5a8b83fdac1d361e86736de2be4ebaaa3 100644 --- a/src/proto_alpha/lib_protocol/constants_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_repr.mli @@ -3,7 +3,7 @@ (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) (* Copyright (c) 2020-2021 Nomadic Labs *) -(* Copyright (c) 2022 Trili Tech *) +(* Copyright (c) 2021-2022 Trili Tech, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -146,6 +146,7 @@ type parametric = { tx_rollup_max_finalized_levels : int; sc_rollup_enable : bool; sc_rollup_origination_size : int; + sc_rollup_challenge_window_in_blocks : int; } val parametric_encoding : parametric Data_encoding.encoding diff --git a/src/proto_alpha/lib_protocol/constants_storage.ml b/src/proto_alpha/lib_protocol/constants_storage.ml index e8853394605bfcafc8ec5bf4eb0a6f96adda6900..0faf23bf19e4d42a696350b12ba0a19562fcfb14 100644 --- a/src/proto_alpha/lib_protocol/constants_storage.ml +++ b/src/proto_alpha/lib_protocol/constants_storage.ml @@ -2,7 +2,7 @@ (* *) (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) -(* Copyright (c) 2022 Trili Tech *) +(* Copyright (c) 2021-2022 Trili Tech, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -197,3 +197,7 @@ let sc_rollup_enable c = let sc_rollup_origination_size c = let constants = Raw_context.constants c in constants.sc_rollup_origination_size + +let sc_rollup_challenge_window_in_blocks c = + let constants = Raw_context.constants c in + constants.sc_rollup_challenge_window_in_blocks diff --git a/src/proto_alpha/lib_protocol/constants_storage.mli b/src/proto_alpha/lib_protocol/constants_storage.mli index 44f53ade3bc0c46d3ac05b533f0031aa480fbe44..c8157fec773dce8d2f1879a08ec6eac84724c592 100644 --- a/src/proto_alpha/lib_protocol/constants_storage.mli +++ b/src/proto_alpha/lib_protocol/constants_storage.mli @@ -3,7 +3,7 @@ (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) (* Copyright (c) 2020-2021 Nomadic Labs *) -(* Copyright (c) 2022 Trili Tech *) +(* Copyright (c) 2021-2022 Trili Tech, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -114,3 +114,5 @@ val delay_increment_per_round : Raw_context.t -> Period_repr.t val sc_rollup_enable : Raw_context.t -> bool val sc_rollup_origination_size : Raw_context.t -> int + +val sc_rollup_challenge_window_in_blocks : Raw_context.t -> int diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index 412936cf04779ff74b73a138f085a599ffd117c2..0f08d863512e3b2fc135c2c8482b89b1e9a3c5bc 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -2,7 +2,7 @@ (* *) (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) -(* Copyright (c) 2022 Trili Tech *) +(* Copyright (c) 2021-2022 Trili Tech, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -937,6 +937,7 @@ let prepare_first_block ~level ~timestamp ctxt = sc_rollup_enable = false; (* The following value is chosen to prevent spam. *) sc_rollup_origination_size = 6_314; + sc_rollup_challenge_window_in_blocks = 20_160; } in add_constants ctxt constants >>= fun ctxt -> return ctxt) diff --git a/src/proto_alpha/lib_protocol/sc_rollup_repr.ml b/src/proto_alpha/lib_protocol/sc_rollup_repr.ml index 1c2048a2d58f6274af8f210b6add20d52e2e4c1f..71aff10f285f64c5b6a0ed629052005fd2bac03d 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_repr.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_repr.ml @@ -140,6 +140,8 @@ end type t = Address.t +module Staker = Signature.Public_key_hash + let description = "A smart contract rollup is identified by a base58 address starting with " ^ Address.prefix @@ -169,6 +171,8 @@ let of_b58check s = | Some (Address.Data hash) -> ok hash | _ -> Error (Format.sprintf "Invalid_sc_rollup_address %s" s) +let pp = Address.pp + let encoding = let open Data_encoding in def @@ -274,6 +278,12 @@ module Commitment = struct (req "predecessor" Commitment_hash.encoding) (req "number_of_messages" Number_of_messages.encoding) (req "number_of_ticks" Number_of_ticks.encoding)) + + let hash commitment = + let commitment_bytes = + Data_encoding.Binary.to_bytes_exn encoding commitment + in + Commitment_hash.hash_bytes [commitment_bytes] end module Kind = struct diff --git a/src/proto_alpha/lib_protocol/sc_rollup_repr.mli b/src/proto_alpha/lib_protocol/sc_rollup_repr.mli index b466ec58e0d1f3eabd7c0fff42998311210a121b..f5220b6ef9cf3789596106c0362ffcd99297f9d5 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_repr.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_repr.mli @@ -35,7 +35,7 @@ essential semantics for the rollup operations to be validated by the layer 1 in case of dispute about a commitment ; - - a database which maintains the finalized operations of the rollup + - a database which maintains the cemented operations of the rollup as well as the potentially-disputed operations. *) @@ -111,15 +111,23 @@ module Commitment : sig } val encoding : t Data_encoding.t + + val hash : t -> Commitment_hash.t end (** A smart contract rollup is identified by its address. *) type t = Address.t +(** A [Staker] is an implicit account, identified by its public key hash. *) +module Staker : + S.SIGNATURE_PUBLIC_KEY_HASH with type t = Signature.Public_key_hash.t + val encoding : t Data_encoding.t val rpc_arg : t RPC_arg.t +val pp : Format.formatter -> t -> unit + (** The data model uses an index of these addresses. *) module Index : Storage_description.INDEX with type t = Address.t diff --git a/src/proto_alpha/lib_protocol/sc_rollup_storage.ml b/src/proto_alpha/lib_protocol/sc_rollup_storage.ml index b72a5a308174ad54ad57f4fde13ccaef8170089a..b062189526b6fbfb9583a1fdda17412dc9589c06 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_storage.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_storage.ml @@ -2,6 +2,7 @@ (* *) (* Open Source License *) (* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -23,13 +24,206 @@ (* *) (*****************************************************************************) +type error += + | (* `Temporary *) Sc_rollup_already_staked + | (* `Temporary *) Sc_rollup_disputed + | (* `Temporary *) Sc_rollup_does_not_exist of Sc_rollup_repr.t + | (* `Temporary *) Sc_rollup_no_conflict + | (* `Temporary *) Sc_rollup_no_stakers + | (* `Temporary *) Sc_rollup_not_staked + | (* `Temporary *) Sc_rollup_not_staked_on_lcc + | (* `Temporary *) Sc_rollup_parent_not_lcc + | (* `Temporary *) Sc_rollup_remove_lcc + | (* `Temporary *) Sc_rollup_staker_backtracked + | (* `Temporary *) Sc_rollup_too_far_ahead + | (* `Temporary *) Sc_rollup_too_recent + | (* `Temporary *) + Sc_rollup_unknown_commitment of + Sc_rollup_repr.Commitment_hash.t + | (* `Temporary *) Sc_rollup_bad_inbox_level + +let () = + let description = "Already staked." in + register_error_kind + `Temporary + ~id:"Sc_rollup_already_staked" + ~title:"Already staked" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_already_staked -> Some () | _ -> None) + (fun () -> Sc_rollup_already_staked) ; + let description = "Attempted to cement a disputed commitment." in + register_error_kind + `Temporary + ~id:"Sc_rollup_disputed" + ~title:"Commitment disputed" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_disputed -> Some () | _ -> None) + (fun () -> Sc_rollup_disputed) ; + let description = "Attempted to use a rollup that has not been originated." in + register_error_kind + `Temporary + ~id:"Sc_rollup_does_not_exist" + ~title:"Rollup does not exist" + ~description + ~pp:(fun ppf x -> + Format.fprintf ppf "Rollup %a does not exist" Sc_rollup_repr.pp x) + Data_encoding.(obj1 (req "rollup" Sc_rollup_repr.encoding)) + (function Sc_rollup_does_not_exist x -> Some x | _ -> None) + (fun x -> Sc_rollup_does_not_exist x) ; + let description = "No conflict." in + register_error_kind + `Temporary + ~id:"Sc_rollup_no_conflict" + ~title:"No conflict" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_no_conflict -> Some () | _ -> None) + (fun () -> Sc_rollup_no_conflict) ; + let description = "No stakers." in + register_error_kind + `Temporary + ~id:"Sc_rollup_no_stakers" + ~title:"No stakers" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_no_stakers -> Some () | _ -> None) + (fun () -> Sc_rollup_no_stakers) ; + let description = "Unknown staker." in + register_error_kind + `Temporary + ~id:"Sc_rollup_not_staked" + ~title:"Unknown staker" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_not_staked -> Some () | _ -> None) + (fun () -> Sc_rollup_not_staked) ; + let description = + "Attempted to withdraw while not staked on the last cemented commitment." + in + register_error_kind + `Temporary + ~id:"Sc_rollup_not_staked_on_lcc" + ~title:"Rollup not staked on LCC" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_not_staked_on_lcc -> Some () | _ -> None) + (fun () -> Sc_rollup_not_staked_on_lcc) ; + let description = "Parent is not cemented." in + register_error_kind + `Temporary + ~id:"Sc_rollup_parent_not_lcc" + ~title:"Parent not cemented" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_parent_not_lcc -> Some () | _ -> None) + (fun () -> Sc_rollup_parent_not_lcc) ; + let description = "Can not remove a cemented commitment." in + register_error_kind + `Temporary + ~id:"Sc_rollup_remove_lcc" + ~title:"Can not remove cemented" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_remove_lcc -> Some () | _ -> None) + (fun () -> Sc_rollup_remove_lcc) ; + let description = "Staker backtracked." in + register_error_kind + `Temporary + ~id:"Sc_rollup_staker_backtracked" + ~title:"Staker backtracked" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_staker_backtracked -> Some () | _ -> None) + (fun () -> Sc_rollup_staker_backtracked) ; + let description = + "Commitment is too far ahead of the last cemented commitment." + in + register_error_kind + `Temporary + ~id:"Sc_rollup_too_far_ahead" + ~title:"Commitment too far ahead" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_too_far_ahead -> Some () | _ -> None) + (fun () -> Sc_rollup_too_far_ahead) ; + let description = + "Attempted to cement a commitment before its refutation deadline." + in + register_error_kind + `Temporary + ~id:"Sc_rollup_too_recent" + ~title:"Commitment too recent" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_too_recent -> Some () | _ -> None) + (fun () -> Sc_rollup_too_recent) ; + let description = "Unknown commitment." in + register_error_kind + `Temporary + ~id:"Sc_rollup_unknown_commitment" + ~title:"Rollup does not exist" + ~description + ~pp:(fun ppf x -> + Format.fprintf + ppf + "Commitment %a does not exist" + Sc_rollup_repr.Commitment_hash.pp + x) + Data_encoding.( + obj1 (req "commitment" Sc_rollup_repr.Commitment_hash.encoding)) + (function Sc_rollup_unknown_commitment x -> Some x | _ -> None) + (fun x -> Sc_rollup_unknown_commitment x) ; + let description = "Attempted to commit to a bad inbox level." in + register_error_kind + `Temporary + ~id:"Sc_rollup_bad_inbox_level" + ~title:"Committed too soon" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_bad_inbox_level -> Some () | _ -> None) + (fun () -> Sc_rollup_bad_inbox_level) ; + () + +(** To be removed once [Lwt_tzresult_syntax] is in the environment. *) +module Lwt_tzresult_syntax = struct + let ( let* ) = ( >>=? ) + + let return = return +end + +module Store = Storage.Sc_rollup +module Commitment = Sc_rollup_repr.Commitment +module Commitment_hash = Sc_rollup_repr.Commitment_hash + let originate ctxt ~kind ~boot_sector = Raw_context.increment_origination_nonce ctxt >>?= fun (ctxt, nonce) -> Sc_rollup_repr.Address.from_nonce nonce >>?= fun address -> Storage.Sc_rollup.PVM_kind.add ctxt address kind >>= fun ctxt -> + Storage.Sc_rollup.Initial_level.add + ctxt + address + (Level_storage.current ctxt).level + >>= fun ctxt -> Storage.Sc_rollup.Boot_sector.add ctxt address boot_sector >>= fun ctxt -> Storage.Sc_rollup.Inbox.init ctxt address Sc_rollup_inbox.empty >>=? fun (ctxt, size_diff) -> + Store.Last_cemented_commitment.init ctxt address Commitment_hash.zero + >>=? fun (ctxt, lcc_size_diff) -> + Store.Staker_count.init ctxt address 0l >>=? fun (ctxt, stakers_size_diff) -> let addresses_size = 2 * Sc_rollup_repr.Address.size in let stored_kind_size = 2 (* because tag_size of kind encoding is 16bits. *) in let boot_sector_size = @@ -41,7 +235,7 @@ let originate ctxt ~kind ~boot_sector = let size = Z.of_int (origination_size + stored_kind_size + boot_sector_size + addresses_size - + size_diff) + + size_diff + lcc_size_diff + stakers_size_diff) in return (address, size, ctxt) @@ -54,6 +248,386 @@ let add_messages ctxt rollup messages = Storage.Sc_rollup.Inbox.update ctxt rollup inbox >>=? fun (ctxt, size) -> return (inbox, Z.of_int size, ctxt) +(** Try to consume n messages. *) +let consume_n_messages ctxt rollup n = + let open Lwt_tzresult_syntax in + let* (ctxt, inbox) = Storage.Sc_rollup.Inbox.get ctxt rollup in + match Sc_rollup_inbox.consume_n_messages n inbox with + | None -> return ctxt + | Some inbox -> + let* (ctxt, size) = Storage.Sc_rollup.Inbox.update ctxt rollup inbox in + assert (Compare.Int.(size < 0)) ; + return ctxt + let inbox ctxt rollup = - Storage.Sc_rollup.Inbox.get ctxt rollup >>=? fun (ctxt, res) -> + let open Lwt_tzresult_syntax in + let* (ctxt, res) = Storage.Sc_rollup.Inbox.get ctxt rollup in return (res, ctxt) + +let last_cemented_commitment ctxt rollup = + let open Lwt_tzresult_syntax in + let* (ctxt, res) = Store.Last_cemented_commitment.find ctxt rollup in + match res with + | None -> fail (Sc_rollup_does_not_exist rollup) + | Some lcc -> return (lcc, ctxt) + +let get_commitment ctxt rollup commitment = + let open Lwt_tzresult_syntax in + let* (ctxt, res) = Store.Commitments.find (ctxt, rollup) commitment in + match res with + | None -> fail (Sc_rollup_unknown_commitment commitment) + | Some commitment -> return (commitment, ctxt) + +let get_predecessor ctxt rollup node = + let open Lwt_tzresult_syntax in + let* (commitment, ctxt) = get_commitment ctxt rollup node in + return (commitment.predecessor, ctxt) + +let find_staker ctxt rollup staker = + let open Lwt_tzresult_syntax in + let* (ctxt, res) = Store.Stakers.find (ctxt, rollup) staker in + match res with + | None -> fail Sc_rollup_not_staked + | Some branch -> return (branch, ctxt) + +let modify_staker_count ctxt rollup f = + let open Lwt_tzresult_syntax in + let* (ctxt, maybe_count) = Store.Staker_count.find ctxt rollup in + let count = Option.value ~default:0l maybe_count in + let* (ctxt, size_diff, _was_bound) = + Store.Staker_count.add ctxt rollup (f count) + in + assert (Compare.Int.(size_diff = 0)) ; + return ctxt + +let get_commitment_stake_count ctxt rollup node = + let open Lwt_tzresult_syntax in + let* (ctxt, maybe_staked_on_commitment) = + Store.Commitment_stake_count.find (ctxt, rollup) node + in + return (Option.value ~default:0l maybe_staked_on_commitment, ctxt) + +(** [set_commitment_added ctxt rollup node current] sets the commitment + addition time of [node] to [current] iff the commitment time was + not previously set, and leaves it unchanged otherwise. + *) +let set_commitment_added ctxt rollup node new_value = + let open Lwt_tzresult_syntax in + let* (ctxt, res) = Store.Commitment_added.find (ctxt, rollup) node in + let new_value = + match res with None -> new_value | Some old_value -> old_value + in + let* (ctxt, size_diff, _was_bound) = + Store.Commitment_added.add (ctxt, rollup) node new_value + in + return (size_diff, ctxt) + +let deallocate ctxt rollup node = + let open Lwt_tzresult_syntax in + if Commitment_hash.(node = zero) then return ctxt + else + let* (ctxt, _size_freed) = + Store.Commitments.remove_existing (ctxt, rollup) node + in + let* (ctxt, _size_freed) = + Store.Commitment_added.remove_existing (ctxt, rollup) node + in + let* (ctxt, _size_freed) = + Store.Commitment_stake_count.remove_existing (ctxt, rollup) node + in + return ctxt + +let modify_commitment_stake_count ctxt rollup node f = + let open Lwt_tzresult_syntax in + let* (count, ctxt) = get_commitment_stake_count ctxt rollup node in + let new_count = f count in + let* (ctxt, size_diff, _was_bound) = + Store.Commitment_stake_count.add (ctxt, rollup) node new_count + in + return (new_count, size_diff, ctxt) + +let increase_commitment_stake_count ctxt rollup node = + let open Lwt_tzresult_syntax in + let* (_new_count, size_diff, ctxt) = + modify_commitment_stake_count ctxt rollup node Int32.succ + in + return (size_diff, ctxt) + +let decrease_commitment_stake_count ctxt rollup node = + let open Lwt_tzresult_syntax in + let* (new_count, _size_diff, ctxt) = + modify_commitment_stake_count ctxt rollup node Int32.pred + in + if Compare.Int32.(new_count <= 0l) then deallocate ctxt rollup node + else return ctxt + +let deposit_stake ctxt rollup staker = + let open Lwt_tzresult_syntax in + let* (lcc, ctxt) = last_cemented_commitment ctxt rollup in + let* (ctxt, res) = Store.Stakers.find (ctxt, rollup) staker in + match res with + | None -> + (* TODO: https://gitlab.com/tezos/tezos/-/issues/2449 + We should lock stake here, and fail if there aren't enough funds. + *) + let* (ctxt, _size) = Store.Stakers.init (ctxt, rollup) staker lcc in + let* ctxt = modify_staker_count ctxt rollup Int32.succ in + return ctxt + | Some _ -> fail Sc_rollup_already_staked + +let withdraw_stake ctxt rollup staker = + let open Lwt_tzresult_syntax in + let* (lcc, ctxt) = last_cemented_commitment ctxt rollup in + let* (ctxt, res) = Store.Stakers.find (ctxt, rollup) staker in + match res with + | None -> fail Sc_rollup_not_staked + | Some staked_on_commitment -> + if Commitment_hash.(staked_on_commitment = lcc) then + (* TODO: https://gitlab.com/tezos/tezos/-/issues/2449 + We should refund stake here. + *) + let* (ctxt, _size_freed) = + Store.Stakers.remove_existing (ctxt, rollup) staker + in + let* ctxt = modify_staker_count ctxt rollup Int32.pred in + modify_staker_count ctxt rollup Int32.pred + else fail Sc_rollup_not_staked_on_lcc + +(* TODO https://gitlab.com/tezos/tezos/-/issues/2548 + These should be protocol constants. See issue for invariant that should be + tested for. *) +let sc_rollup_max_lookahead = 30_000l + +let sc_rollup_commitment_frequency = 20 + +(* 76 for Commitments entry + 4 for Commitment_stake_count entry + 4 for Commitment_added entry *) +let sc_rollup_commitment_storage_size_in_bytes = 84 + +let assert_commitment_not_too_far_ahead ctxt rollup lcc commitment = + let open Lwt_tzresult_syntax in + let* (ctxt, min_level) = + if Commitment_hash.(lcc = zero) then + let* level = Store.Initial_level.get ctxt rollup in + return (ctxt, level) + else + let* (lcc, ctxt) = get_commitment ctxt rollup lcc in + return (ctxt, Commitment.(lcc.inbox_level)) + in + let max_level = Commitment.(commitment.inbox_level) in + if + Compare.Int32.( + sc_rollup_max_lookahead < Raw_level_repr.diff max_level min_level) + then fail Sc_rollup_too_far_ahead + else return ctxt + +let assert_commitment_frequency ctxt rollup commitment check = + let open Lwt_tzresult_syntax in + let pred = Commitment.(commitment.predecessor) in + let* (ctxt, pred_level) = + if Commitment_hash.(pred = zero) then + let* level = Store.Initial_level.get ctxt rollup in + return (ctxt, level) + else + let* (pred, ctxt) = get_commitment ctxt rollup commitment.predecessor in + return (ctxt, Commitment.(pred.inbox_level)) + in + if + Raw_level_repr.( + check + commitment.inbox_level + (add pred_level sc_rollup_commitment_frequency)) + then return ctxt + else fail Sc_rollup_bad_inbox_level + +(** Check invariants on [inbox_level], enforcing overallocation of storage and + regularity of block prorudction. + + The constants used by [assert_refine_conditions_met] must be chosen such + that the maximum cost of storage allocated by each staker at most the size + of their deposit. + *) +let assert_refine_conditions_met ctxt rollup lcc commitment = + let open Lwt_tzresult_syntax in + let* ctxt = assert_commitment_not_too_far_ahead ctxt rollup lcc commitment in + (* We want to check the following inequalities on [commitment.inbox_level], + [commitment.predecessor.inbox_level] and the constant [sc_rollup_commitment_frequency]. + + - Greater-than-or-equal (>=), to ensure inbox_levels are monotonically + increasing. along each branch of commitments. Together with + [assert_commitment_not_too_far_ahead] this is sufficient to limit the + depth of the commitment tree, which is also the number commitments stored + per staker. This constraint must be enforced at submission time. + + - Equality (=), so that that L2 blocks are produced at a regular rate. This + ensures that there is only ever one branch of correct commitments, + simplifying refutation logic. This could also be enforced at refutation time + rather than submission time, but doing it here works too. + + Because [a >= b && a = b] is equivalent to [a = b], we can the latter as + an optimization. + *) + let check = Raw_level_repr.( = ) in + assert_commitment_frequency ctxt rollup commitment check + +let refine_stake ctxt rollup level staker commitment = + let open Lwt_tzresult_syntax in + let* (lcc, ctxt) = last_cemented_commitment ctxt rollup in + let* (staked_on, ctxt) = find_staker ctxt rollup staker in + let* ctxt = assert_refine_conditions_met ctxt rollup lcc commitment in + let new_hash = Commitment.hash commitment in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/2559 + Add a test checking that L2 nodes can catch up after going offline. *) + let rec go node ctxt = + (* WARNING: Do NOT reorder this sequence of ifs. + we must check for staked_on before LCC, since refining + from the LCC to another commit is a valid operation. *) + if Commitment_hash.(node = staked_on) then ( + (* Previously staked commit found: + Insert new commitment if not existing *) + let* (ctxt, commitment_size_diff, _was_bound) = + Store.Commitments.add (ctxt, rollup) new_hash commitment + in + let* (commitment_added_size_diff, ctxt) = + set_commitment_added ctxt rollup new_hash level + in + let* (ctxt, staker_count_diff) = + Store.Stakers.update (ctxt, rollup) staker new_hash + in + let* (stake_count_size_diff, ctxt) = + increase_commitment_stake_count ctxt rollup new_hash + in + let size_diff = + commitment_size_diff + commitment_added_size_diff + + stake_count_size_diff + staker_count_diff + in + (* First submission adds [sc_rollup_commitment_storage_size_in_bytes] to storage. + Later submission adds 0 due to content-addressing. *) + assert ( + Compare.Int.( + size_diff = 0 + || size_diff = sc_rollup_commitment_storage_size_in_bytes)) ; + return (new_hash, ctxt) (* See WARNING above. *)) + else if Commitment_hash.(node = lcc) then + (* We reached the LCC, but [staker] is not staked directly on it. + Thus, we backtracked. Note that everyone is staked indirectly on + the LCC. *) + fail Sc_rollup_staker_backtracked + else + let* (pred, ctxt) = get_predecessor ctxt rollup node in + let* (_size, ctxt) = increase_commitment_stake_count ctxt rollup node in + (go [@ocaml.tailcall]) pred ctxt + in + go Commitment.(commitment.predecessor) ctxt + +let cement_commitment ctxt rollup level new_lcc = + let open Lwt_tzresult_syntax in + let refutation_deadline_blocks = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + (* get is safe, as Staker_count is initialized on origination *) + let* (ctxt, total_staker_count) = Store.Staker_count.get ctxt rollup in + if Compare.Int32.(total_staker_count <= 0l) then fail Sc_rollup_no_stakers + else + let* (old_lcc, ctxt) = last_cemented_commitment ctxt rollup in + let* (new_lcc_commitment, ctxt) = get_commitment ctxt rollup new_lcc in + let* (ctxt, new_lcc_added) = + Store.Commitment_added.get (ctxt, rollup) new_lcc + in + if Commitment_hash.(new_lcc_commitment.predecessor <> old_lcc) then + fail Sc_rollup_parent_not_lcc + else + let* (new_lcc_stake_count, ctxt) = + get_commitment_stake_count ctxt rollup new_lcc + in + if Compare.Int32.(total_staker_count <> new_lcc_stake_count) then + fail Sc_rollup_disputed + else if + Raw_level_repr.(level < add new_lcc_added refutation_deadline_blocks) + then fail Sc_rollup_too_recent + else + (* update LCC *) + let* (ctxt, lcc_size_diff) = + Store.Last_cemented_commitment.update ctxt rollup new_lcc + in + assert (Compare.Int.(lcc_size_diff = 0)) ; + (* At this point we know all stakers are implicitly staked + on the new LCC, and no one is directly staked on the old LCC. We + can safely deallocate the old LCC. + *) + let* ctxt = deallocate ctxt rollup old_lcc in + let* ctxt = + consume_n_messages + ctxt + rollup + (Int32.to_int + @@ Sc_rollup_repr.Number_of_messages.to_int32 + new_lcc_commitment.number_of_messages) + in + let* (ctxt, _size) = + Store.Commitments.remove_existing (ctxt, rollup) new_lcc + in + return ctxt + +module Successor_map = Commitment_hash.Map + +type conflict_point = Commitment_hash.t * Commitment_hash.t + +let get_conflict_point ctxt rollup staker1 staker2 = + let open Lwt_tzresult_syntax in + let* (lcc, ctxt) = last_cemented_commitment ctxt rollup in + let* (staker1_branch, ctxt) = find_staker ctxt rollup staker1 in + let* (staker2_branch, ctxt) = find_staker ctxt rollup staker2 in + (* Build a map from commitments on the staker1 branch to their direct + successor on this branch. *) + let* (staker1_succ_map, ctxt) = + let rec go node prev_map ctxt = + if Commitment_hash.(node = lcc) then return (prev_map, ctxt) + else + let* (pred, ctxt) = get_predecessor ctxt rollup node in + let new_map = Successor_map.add pred node prev_map in + (go [@ocaml.tailcall]) pred new_map ctxt + in + go staker1_branch Successor_map.empty ctxt + in + (* Traverse from staker2 towards LCC. *) + if Successor_map.mem staker2_branch staker1_succ_map then + (* The staker1 branch contains the tip of the staker2 branch. + Commitments are perfect agreement, or in partial agreement with staker1 + ahead. *) + fail Sc_rollup_no_conflict + else + let rec go node ctxt = + if Commitment_hash.(node = staker1_branch) then + (* The staker2 branch contains the tip of the staker1 branch. + The commitments are in partial agreement with staker2 ahead. *) + fail Sc_rollup_no_conflict + else + let right = node in + let* (pred, ctxt) = get_predecessor ctxt rollup node in + match Successor_map.find pred staker1_succ_map with + | None -> (go [@ocaml.tailcall]) pred ctxt + | Some left -> return ((left, right), ctxt) + in + go staker2_branch ctxt + +let remove_staker ctxt rollup staker = + let open Lwt_tzresult_syntax in + let* (lcc, ctxt) = last_cemented_commitment ctxt rollup in + let* (ctxt, res) = Store.Stakers.find (ctxt, rollup) staker in + match res with + | None -> fail Sc_rollup_not_staked + | Some staked_on -> + if Commitment_hash.(staked_on = lcc) then fail Sc_rollup_remove_lcc + else + let* (ctxt, _size_diff) = + Store.Stakers.remove_existing (ctxt, rollup) staker + in + let* ctxt = modify_staker_count ctxt rollup Int32.pred in + let rec go node ctxt = + if Commitment_hash.(node = lcc) then return ctxt + else + let* (pred, ctxt) = get_predecessor ctxt rollup node in + let* ctxt = decrease_commitment_stake_count ctxt rollup node in + (go [@ocaml.tailcall]) pred ctxt + in + go staked_on ctxt diff --git a/src/proto_alpha/lib_protocol/sc_rollup_storage.mli b/src/proto_alpha/lib_protocol/sc_rollup_storage.mli index f8350fe22f4bb26f0afdd39a55e425b36cad2efd..26b5da30eb61323fdcd50091a7cb5c73d6241c7e 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_storage.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_storage.mli @@ -2,6 +2,7 @@ (* *) (* Open Source License *) (* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -23,6 +24,123 @@ (* *) (*****************************************************************************) +(** Defines storage for Smart Contract Optimistic Rollups. + + {2 Commitments} + + [Commitment]s are stored directly in the L1 context. Commitments are + immutable and content-addressed, and can be indexed by a [Commitment_hash]. + + A commitment represents a claim about the state of a PVM. + + We also keep auxiliary state about each commitment, namely: + + {ul + {li When it was first added.} + {li Its current number of stakers.} + } + + This auxiliary data is not part of the commitment itself. They represent + information that the L1 knows about the claim, not the claim itself. + + {3 Predecessors and Boot state} + Each commitment contains the hash of its {i predecessor}. Multiple + commitments can have the same predecessor. Therefore, commitments form + a Merkle tree. + + Conceptually the root of this tree is the [Commitment_hash.zero]. This + commitment claims that the PVM (Proof-generating Virtual Machine) is in a + pre-boot state and waiting to start booting by interpreting the boot sector with + respect to the Machine semantics. + + {3 Cemented and Disputable commitments} + Commitments accepted as true by the protocol are referred to as Cemented. + + {3 Stakers} + The Stakers table maps Stakers (implicit accounts) to commitments. + + Let [Stakers(S)] mean "looking up the key S in [Stakers]". + + A staker [S] is directly staked on [C] if [Stakers(S) = C]. A staker [S] + is indirectly staked on [C] if [C] is an ancestor of [Stakers(S)] in the commitment tree. + + {3 Dispute} + Commitments that have at least one sibling are referred to as Disputed. + More formally, a commitment C is disputed if at least one staker is not + (directly or indirectly) staked on C. + + {3 Dispute resolution} + The rollup protocol ensures that all disputes are resolved before cementing + a commitment. Therefore, cemented commitments form a list rather than a tree. + + In the context we only store the Last Cemented Commitment (LCC), which is + by definition a descendant of [zero]. We also store all Disputable + commitments that have at least one Staker. + + For example, assuming the full set of commitments for a rollup + looks like this: + + {[ + LCC staker1 staker2 + | | | + | V | + V --c3 | + zero--c1 --c2--/ | + \ V + --c4------ c5 + ]} + then commitments [c2..c5] will be stored in the context. + + {3 Conflicts} + + Let Commitments(S) be the set of commitments directly staked on by staker S. + + Two stakers A and B are: + + {ul + {li In total agreement iff Commitments(A) = Commitments(B).} + {li In partial agreement iff either Commitments(A) ⊂ Commitments(B), or + Commitments(B) ⊂ Commitments(A).} + {li In conflict iff they are neither in total or partial agreement.}} + + We can further refine a conflict to note what they are in conflict about, + e.g. they may be in conflict about the inbox, about execution, or both. We + can resolve conflicts by first resolving the conflict about inbox, then + about execution (since execution is irrelevant if the inbox is not + correct). + *) + +type error += + | (* `Temporary *) + Sc_rollup_does_not_exist of Sc_rollup_repr.t + | (* `Temporary *) + Sc_rollup_already_staked + | (* `Temporary *) + Sc_rollup_not_staked_on_lcc + | (* `Temporary *) + Sc_rollup_staker_backtracked + | (* `Temporary *) + Sc_rollup_unknown_commitment of + Sc_rollup_repr.Commitment_hash.t + | (* `Temporary *) + Sc_rollup_parent_not_lcc + | (* `Temporary *) + Sc_rollup_too_far_ahead + | (* `Temporary *) + Sc_rollup_too_recent + | (* `Temporary *) + Sc_rollup_no_stakers + | (* `Temporary *) + Sc_rollup_disputed + | (* `Temporary *) + Sc_rollup_no_conflict + | (* `Temporary *) + Sc_rollup_not_staked + | (* `Temporary *) + Sc_rollup_remove_lcc + | (* `Temporary *) + Sc_rollup_bad_inbox_level + (** [originate context ~kind ~boot_sector] produces an address [a] for a smart contract rollup using the origination nonce found in [context]. This function also initializes the storage with a new @@ -46,18 +164,198 @@ val kind : (** [add_message context rollup msg] adds [msg] to [rollup]'s inbox. - This function is carbonated and returns the updated context as well as - the size diff. *) + This function returns the updated context as well as the size diff. *) val add_messages : Raw_context.t -> Sc_rollup_repr.t -> string list -> (Sc_rollup_inbox.t * Z.t * Raw_context.t) tzresult Lwt.t -(** [inbox context rollup] returns the current state of the inbox. - - This function is carbonated. *) +(** [inbox context rollup] returns the current state of the inbox. *) val inbox : Raw_context.t -> Sc_rollup_repr.t -> (Sc_rollup_inbox.t * Raw_context.t) tzresult Lwt.t + +(** [deposit_stake context rollup staker] stakes [staker] at the last + cemented commitment, freezing [sc_rollup_deposit] from [staker]'s account + balance. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + {li [Sc_rollup_already_staked] if [staker] is already staked} + {li [Sc_rollup_staker_funds_too_low] if [staker] does not have enough funds to cover the deposit} + } + + This should usually be followed by [refine_stake] to stake on a + specific commitment. + + This function does not authenticate the staker. *) +val deposit_stake : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + Raw_context.t tzresult Lwt.t + +(** [withdraw_stake context rollup staker] removes [staker] and returns + any deposit previously frozen by [deposit_stake]. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + {li [Sc_rollup_not_staked_on_lcc] if [staker] is not staked on the last + cemented commitment} + } + + Note that it is not possible to be staked on a Cemented commitment other + than the Last, because of Cementation Rule #4. See [cement_commitment] + for details. + + By design, the operation wrapping this should {i not} be authenticated, + as it may be necessary for nodes on the honest branch to refund stakers on + the LCC. They must do so by using [withdraw_stake] as they are implicitly + staked on the LCC and can not dispute it. *) +val withdraw_stake : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + Raw_context.t tzresult Lwt.t + +(** [refine_stake context rollup level staker commitment] moves the stake of + [staker] to [commitment]. Because we do not assume any form of coordination + between validators, we do not distinguish between {i adding new} + commitments and {i staking on existing commitments}. The storage of + commitments is content-addressable to minimize storage duplication. + + [level] should be the current Tezos block level. This must be monotonically + increasing in subsequent calls to [refine_stake] and [cement_commitment], + or behavior is undefined. + + The first time a commitment hash is staked on, it is assigned a deadline, + which is counted in Tezos blocks (levels). Further stakes on the block does + not affect the deadline. The commitment can not be cemented before the + deadline has expired. Note that if a commitment is removed due to disputes + and then re-entered, a later deadline may be assigned. Assuming one honest + staker is always available, this only affects invalid commitments. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + {li [Sc_rollup_too_far_ahead] if [staker] would be more than + [sc_rollup_max_future_commitments] ahead of the Last Cemented Commitment} + {li [Sc_rollup_bad_inbox_level] if [commitment]'s predecessor is + less than [sc_rollup_commitment_frequency] blocks ahead} + {li [Sc_rollup_not_staked] if [staker] is not staked} + {li [Sc_rollup_staker_backtracked] if [staker] is not staked on an ancestor of [commitment]} + {li [Sc_rollup_unknown_commitment] if the parent of the given commitment does not exist} + } + + Returns the hash of the given commitment. + + This function does not authenticate the staker. *) +val refine_stake : + Raw_context.t -> + Sc_rollup_repr.t -> + Raw_level_repr.t -> + Sc_rollup_repr.Staker.t -> + Sc_rollup_repr.Commitment.t -> + (Sc_rollup_repr.Commitment_hash.t * Raw_context.t) tzresult Lwt.t + +(** [last_cemented_commitment context rollup] returns the last cemented + commitment of the rollup. + + If no commitments have been cemented, the rollup is said to be in a + pre-boot state, and [last_cemented_commitment = Commitment_hash.zero]. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} *) +val last_cemented_commitment : + Raw_context.t -> + Sc_rollup_repr.t -> + (Sc_rollup_repr.Commitment_hash.t * Raw_context.t) tzresult Lwt.t + +(** [cement_commitment context rollup commitment] cements the given + commitment. + + [level] should be the current Tezos block level. This must be monotonically + increasing in subsequent calls to [refine_stake] and [cement_commitment], + or behavior is undefined. + + For cementing to succeed, the following must hold: + {ol + {li The deadline for [commitment] must have passed.} + {li The predecessor of [commitment] must be the Last Cemented Commitment.} + {li There must be at least one staker.} + {li All stakers must be indirectly staked on [commitment].} + } + + If successful, [last_cemented_commitment] is set to the given [commitment] and + the appropriate amount of inbox messages is consumed. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + {li [Sc_rollup_unknown_commitment] if [commitment] does not exist} + {li [Sc_rollup_parent_not_lcc] if [commitment] is not the child of the last cemented commitment} + {li [Sc_rollup_too_recent] if [commitment] has not passed its deadline} + {li [Sc_rollup_no_stakers] if there are zero stakers} + {li [Sc_rollup_disputed] if at least one staker is not staked on [commitment]} + } *) +val cement_commitment : + Raw_context.t -> + Sc_rollup_repr.t -> + Raw_level_repr.t -> + Sc_rollup_repr.Commitment_hash.t -> + Raw_context.t tzresult Lwt.t + +type conflict_point = + Sc_rollup_repr.Commitment_hash.t * Sc_rollup_repr.Commitment_hash.t + +(** [get_conflict_point context rollup staker1 staker2] returns the first point + of disagreement between the given stakers. The returned commitments are + distinct, and have the same [parent] commitment. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + {li [Sc_rollup_no_conflict] if [staker1] is staked on an ancestor of the commitment staked on by [staker2], or vice versa} + } *) +val get_conflict_point : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + Sc_rollup_repr.Staker.t -> + (conflict_point * Raw_context.t) tzresult Lwt.t + +(** [get_commitment context rollup commitment_hash] returns the commitment with the given hash. + + May fail with: + {ul + {li [Sc_rollup_unknown_commitment] if [rollup] or [commitment] does not exist} + } *) +val get_commitment : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Commitment_hash.t -> + (Sc_rollup_repr.Commitment.t * Raw_context.t) tzresult Lwt.t + +(** [remove_staker context rollup staker] forcibly removes the given [staker] + and confiscates their frozen deposits. + + Any commitments no longer staked on are removed and storage reclaimed by + [remove_staker]. Because of this there is no need to explicitly reject + commitments. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + {li [Sc_rollup_not_staked] if [staker] is not staked} + {li [Sc_rollup_remove_lcc] if [staker] is staked on a cemented commitment} + } *) +val remove_staker : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + Raw_context.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 566424dcee48ad537cb6d3ccca0ae144154da382..aa1b3825d99b75b9d2fb634e153c2a009344d202 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -839,18 +839,9 @@ module Public_key_hash = struct let to_path (key : public_key_hash) l = match key with - | Ed25519 h -> ( - match Path_Ed25519.to_path h l with - | s :: t -> "ed25519" :: s :: t - | _ -> raise (Invalid_argument "Error: No path in ed25519")) - | Secp256k1 h -> ( - match Path_Secp256k1.to_path h l with - | s :: t -> "secp256k1" :: s :: t - | _ -> raise (Invalid_argument "Error: No path in secp256k1")) - | P256 h -> ( - match Path_P256.to_path h l with - | s :: t -> "p256" :: s :: t - | _ -> raise (Invalid_argument "Error: No path in p256")) + | Ed25519 h -> "ed25519" :: Path_Ed25519.to_path h l + | Secp256k1 h -> "secp256k1" :: Path_Secp256k1.to_path h l + | P256 h -> "p256" :: Path_P256.to_path h l let of_path : _ -> public_key_hash option = function | "ed25519" :: rest -> ( @@ -871,8 +862,8 @@ module Public_key_hash = struct let l1 = Path_Ed25519.path_length and l2 = Path_Secp256k1.path_length and l3 = Path_P256.path_length in - assert (match (l1, l2, l3) with (1, 1, 1) -> true | _ -> false) ; - 2 + assert (Compare.Int.(l1 = l2 && l2 = l3)) ; + l1 + 1 end module Public_key_hash_index = Make_index (Public_key_hash) @@ -1529,6 +1520,17 @@ module Sc_rollup = struct let encoding = Sc_rollup_repr.PVM.boot_sector_encoding end) + module Initial_level = + Indexed_context.Make_map + (struct + let name = ["initial_level"] + end) + (struct + type t = Raw_level_repr.t + + let encoding = Raw_level_repr.encoding + end) + module Inbox = Indexed_context.Make_carbonated_map (struct @@ -1540,10 +1542,10 @@ module Sc_rollup = struct let encoding = Sc_rollup_inbox.encoding end) - module Last_final_commitment = + module Last_cemented_commitment = Indexed_context.Make_carbonated_map (struct - let name = ["last_final_commitment"] + let name = ["last_cemented_commitment"] end) (struct type t = Sc_rollup_repr.Commitment_hash.t @@ -1564,10 +1566,10 @@ module Sc_rollup = struct let encoding = Sc_rollup_repr.Commitment_hash.encoding end) - module Stakers_size = + module Staker_count = Indexed_context.Make_carbonated_map (struct - let name = ["stakers_size"] + let name = ["staker_count"] end) (struct type t = int32 @@ -1600,4 +1602,17 @@ module Sc_rollup = struct let encoding = Data_encoding.int32 end) + + module Commitment_added = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitment_added"] + end)) + (Make_index (Sc_rollup_repr.Commitment_hash_index)) + (struct + type t = Raw_level_repr.t + + let encoding = Raw_level_repr.encoding + end) end diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 7d3c9c0fff9ba85027d0b98c74e60df9a7a39ef0..4cefe26a75fd6072a2cfb14790ec74e8617ca2f5 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -666,9 +666,11 @@ module Sc_rollup : sig - a PVM kind (provided at creation time, read-only) - a boot sector (provided at creation time, read-only) + - the L1 block level at which the rollup was created - a merkelized inbox, of which only the root hash is stored - - a tree of commitments, rooted at the last finalized commitment + - a tree of commitments, rooted at the last cemented commitment - a map from stakers to commitments + - a map from commitments to the time (level) of its first insertion For performance reasons we also store (per rollup): @@ -689,13 +691,19 @@ module Sc_rollup : sig and type value = Sc_rollup_repr.PVM.boot_sector and type t := Raw_context.t + module Initial_level : + Indexed_data_storage + with type key = Sc_rollup_repr.t + and type value = Raw_level_repr.t + and type t := Raw_context.t + module Inbox : Non_iterable_indexed_carbonated_data_storage with type key = Sc_rollup_repr.t and type value = Sc_rollup_inbox.t and type t := Raw_context.t - module Last_final_commitment : + module Last_cemented_commitment : Non_iterable_indexed_carbonated_data_storage with type key = Sc_rollup_repr.t and type value = Sc_rollup_repr.Commitment_hash.t @@ -707,13 +715,13 @@ module Sc_rollup : sig and type value = Sc_rollup_repr.Commitment_hash.t and type t = Raw_context.t * Sc_rollup_repr.t - (** Cache: This should always be the size of [Stakers]. + (** Cache: This should always be the number of entries in [Stakers]. Combined with {!Commitment_stake_count} (see below), this ensures we can - check that all stakers agree on a commitment prior to finalization in + check that all stakers agree on a commitment prior to cementing it in O(1) - rather than O(n) reads. *) - module Stakers_size : + module Staker_count : Non_iterable_indexed_carbonated_data_storage with type key = Sc_rollup_repr.t and type value = int32 @@ -750,4 +758,10 @@ module Sc_rollup : sig with type key = Sc_rollup_repr.Commitment_hash.t and type value = int32 and type t = Raw_context.t * Sc_rollup_repr.t + + module Commitment_added : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_repr.Commitment_hash.t + and type value = Raw_level_repr.t + and type t = Raw_context.t * Sc_rollup_repr.t end diff --git a/src/proto_alpha/lib_protocol/test/helpers/assert.ml b/src/proto_alpha/lib_protocol/test/helpers/assert.ml index a68d43f6f3b9e9dea68e156ed967dc21df1d40c7..79b8d503a56450cfa06bd0adc4feeb9ed88583ac 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/assert.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/assert.ml @@ -2,6 +2,7 @@ (* *) (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Trili Tech, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -114,6 +115,13 @@ let equal_bool ~loc (a : bool) (b : bool) = let not_equal_bool ~loc (a : bool) (b : bool) = not_equal ~loc Bool.equal "Booleans are equal" Format.pp_print_bool a b +(* string *) +let equal_string ~loc (a : string) (b : string) = + equal ~loc String.equal "Strings aren't equal" Format.pp_print_string a b + +let not_equal_string ~loc (a : string) (b : string) = + not_equal ~loc String.equal "Strings are equal" Format.pp_print_string a b + (* tez *) let equal_tez ~loc (a : Alpha_context.Tez.t) (b : Alpha_context.Tez.t) = let open Alpha_context in diff --git a/src/proto_alpha/lib_protocol/test/unit/main.ml b/src/proto_alpha/lib_protocol/test/unit/main.ml index 957b921c7903714f96a312729ad4210c4002c9b1..9625870e61d85669af43b7957bb6df51c2e838b2 100644 --- a/src/proto_alpha/lib_protocol/test/unit/main.ml +++ b/src/proto_alpha/lib_protocol/test/unit/main.ml @@ -68,6 +68,7 @@ let () = Unit_test.spec "receipt encodings" Test_receipt.tests; Unit_test.spec "saturation arithmetic" Test_saturation.tests; Unit_test.spec "gas monad" Test_gas_monad.tests; + Unit_test.spec "Sc_rollup_storage.ml" Test_sc_rollup_storage.tests; Unit_test.spec "tx rollup l2" Test_tx_rollup_l2.tests; Unit_test.spec "tx rollup l2 apply" Test_tx_rollup_l2_apply.tests; ] diff --git a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..931241f026157b772e94d361be6287e1ff1b1def --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml @@ -0,0 +1,798 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Sc_rollup_storage + Invocation: dune exec src/proto_alpha/lib_protocol/test/unit/main.exe \ + -- test "^\[Unit\] Sc_rollup_storage.ml$" + Subject: Tests for the gas monad module +*) + +open Protocol +open Lwt_result_syntax + +(** Lift a computation using using environment errors to use shell errors. *) +let lift k = Lwt.map Environment.wrap_tzresult k + +(** Trivial assertion. + + By convention, context is passed linearly as [ctxt]. This takes a context + argument to allow this. +*) +let assert_true _ctxt = return () + +(** Assert that the computation fails with the given message. *) +let assert_fails_with ~loc k msg = + let expected_error_msg = "Error:\n " ^ msg ^ "\n" in + k >>= function + | Ok _ -> Stdlib.failwith "Expected failure" + | Error err -> + let actual_error_msg : string = + Format.asprintf "%a" Environment.Error_monad.pp_trace err + in + Assert.equal_string ~loc expected_error_msg actual_error_msg + +(** Assert commitment hash equality. + + By convention, context is passed linearly as [ctxt]. This takes a context + argument to allow this. + *) +let assert_commitment_hash_equal ~loc _ctxt x y = + Assert.equal + ~loc + Sc_rollup_repr.Commitment_hash.equal + "Compare commitment hash" + Sc_rollup_repr.Commitment_hash.pp + x + y + +let new_context () = + let* (b, _contracts) = Context.init 1 in + Incremental.begin_construction b >|=? fun inc -> + let state = Incremental.validation_state inc in + let ctxt = state.ctxt in + (* Necessary to originate rollups. *) + let ctxt = Alpha_context.Origination_nonce.init ctxt Operation_hash.zero in + Alpha_context.Internal_for_tests.to_raw ctxt + +let new_sc_rollup ctxt = + let* (rollup, _size, ctxt) = + Sc_rollup_storage.originate + ctxt + ~kind:Example_arith + ~boot_sector:(Sc_rollup_repr.PVM.boot_sector_of_string "") + in + return (rollup, ctxt) + +let test_deposit_to_missing_rollup () = + let* ctxt = new_context () in + let rollup = Sc_rollup_repr.Address.hash_bytes [] in + let staker = Sc_rollup_repr.Staker.zero in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.deposit_stake ctxt rollup staker) + (* Hash of empty byte sequence *) + "Rollup scr1Ew52VCdi6nF1JuokRGMqfmSeiAEXymW2m does not exist" + +let test_initial_state_is_pre_boot () = + let* ctxt = new_context () in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let* (lcc, ctxt) = + lift @@ Sc_rollup_storage.last_cemented_commitment ctxt rollup + in + assert_commitment_hash_equal + ~loc:__LOC__ + ctxt + lcc + Sc_rollup_repr.Commitment_hash.zero + +let test_deposit_to_existing_rollup () = + let* ctxt = new_context () in + lift + @@ let* (rollup, ctxt) = new_sc_rollup ctxt in + let staker = + Signature.Public_key_hash.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker in + assert_true ctxt + +let test_removing_staker_from_lcc_fails () = + let* ctxt = new_context () in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker = + Signature.Public_key_hash.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.remove_staker ctxt rollup staker) + "Can not remove a cemented commitment." + +let test_deposit_then_withdraw () = + let* ctxt = new_context () in + lift + @@ let* (rollup, ctxt) = new_sc_rollup ctxt in + let staker = + Signature.Public_key_hash.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker in + let* ctxt = Sc_rollup_storage.withdraw_stake ctxt rollup staker in + assert_true ctxt + +let test_can_not_stake_twice () = + let* ctxt = new_context () in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker = + Signature.Public_key_hash.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.deposit_stake ctxt rollup staker) + "Already staked." + +let test_withdraw_when_not_staked () = + let* ctxt = new_context () in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker = + Signature.Public_key_hash.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.withdraw_stake ctxt rollup staker) + "Unknown staker." + +let test_withdrawing_twice () = + let* ctxt = new_context () in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker = + Signature.Public_key_hash.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker in + let* ctxt = lift @@ Sc_rollup_storage.withdraw_stake ctxt rollup staker in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.withdraw_stake ctxt rollup staker) + "Unknown staker." + +let number_of_messages_exn n = + match Sc_rollup_repr.Number_of_messages.of_int32 n with + | Some x -> x + | None -> Stdlib.failwith "Bad Number_of_messages" + +let number_of_ticks_exn n = + match Sc_rollup_repr.Number_of_ticks.of_int32 n with + | Some x -> x + | None -> Stdlib.failwith "Bad Number_of_ticks" + +let test_deposit_then_refine () = + let* ctxt = new_context () in + let level = (Raw_context.current_level ctxt).level in + lift + @@ let* (rollup, ctxt) = new_sc_rollup ctxt in + let staker = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker in + let commitment = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (_node, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level staker commitment + in + assert_true ctxt + +let test_cement () = + let* ctxt = new_context () in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let level_0 = (Raw_context.current_level ctxt).level in + let level_after = Raw_level_repr.add level_0 challenge_window in + lift + @@ let* (rollup, ctxt) = new_sc_rollup ctxt in + let staker = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker in + let commitment = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level_0 staker commitment + in + let* ctxt = + Sc_rollup_storage.cement_commitment ctxt rollup level_after c1 + in + assert_true ctxt + +let test_cement_unknown_commitment_fails () = + let* ctxt = new_context () in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let level_0 = (Raw_context.current_level ctxt).level in + let level_after = Raw_level_repr.add level_0 challenge_window in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker = + Sc_rollup_repr.Staker.of_b58check_exn "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.cement_commitment + ctxt + rollup + level_after + Sc_rollup_repr.Commitment_hash.zero) + "Commitment scc12XhSULdV8bAav21e99VYLTpqAjTd7NU8Mn4zFdKPSA8auMbggG does \ + not exist" + +let test_cement_with_zero_stakers_fails () = + let* ctxt = new_context () in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let level_0 = (Raw_context.current_level ctxt).level in + let level_after = Raw_level_repr.add level_0 challenge_window in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker = + Sc_rollup_repr.Staker.of_b58check_exn "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker in + let commitment = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + lift @@ Sc_rollup_storage.refine_stake ctxt rollup level_0 staker commitment + in + let* ctxt = lift @@ Sc_rollup_storage.remove_staker ctxt rollup staker in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.cement_commitment ctxt rollup level_after c1) + "No stakers." + +let test_cement_fail_too_recent () = + let* ctxt = new_context () in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let level = (Raw_context.current_level ctxt).level in + let level_after = Raw_level_repr.add level (challenge_window - 1) in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker = + Sc_rollup_repr.Staker.of_b58check_exn "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker in + let commitment = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + lift @@ Sc_rollup_storage.refine_stake ctxt rollup level staker commitment + in + let* () = + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.cement_commitment ctxt rollup level c1) + "Attempted to cement a commitment before its refutation deadline." + in + let* () = + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.cement_commitment ctxt rollup level_after c1) + "Attempted to cement a commitment before its refutation deadline." + in + assert_true ctxt + +let test_cement_deadline_uses_oldest_add_time () = + let* ctxt = new_context () in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let level_0 = (Raw_context.current_level ctxt).level in + let level_after = Raw_level_repr.add level_0 challenge_window in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker1 = + Sc_rollup_repr.Staker.of_b58check_exn "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let staker2 = + Sc_rollup_repr.Staker.of_b58check_exn "tz1RikjCkrEde1QQmuesp796jCxeiyE6t3Vo" + in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker1 in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker2 in + let commitment = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + lift + @@ Sc_rollup_storage.refine_stake ctxt rollup level_0 staker1 commitment + in + let* (c2, ctxt) = + lift + @@ Sc_rollup_storage.refine_stake ctxt rollup level_after staker2 commitment + in + let* ctxt = + lift @@ Sc_rollup_storage.cement_commitment ctxt rollup level_after c1 + in + assert_commitment_hash_equal ~loc:__LOC__ ctxt c1 c2 + +let test_withdrawal_fails_when_not_staked_on_lcc () = + let* ctxt = new_context () in + let level = (Raw_context.current_level ctxt).level in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker = + Sc_rollup_repr.Staker.of_b58check_exn "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker in + let commitment = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (_node, ctxt) = + lift @@ Sc_rollup_storage.refine_stake ctxt rollup level staker commitment + in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.withdraw_stake ctxt rollup staker) + "Attempted to withdraw while not staked on the last cemented commitment." + +let test_stake_on_existing_node () = + let* ctxt = new_context () in + let level = (Raw_context.current_level ctxt).level in + lift + @@ let* (rollup, ctxt) = new_sc_rollup ctxt in + let staker1 = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let staker2 = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1RikjCkrEde1QQmuesp796jCxeiyE6t3Vo" + in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker1 in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker2 in + let commitment = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (_node, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level staker1 commitment + in + let* (_node, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level staker2 commitment + in + assert_true ctxt + +let test_cement_with_two_stakers () = + let* ctxt = new_context () in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let level_0 = (Raw_context.current_level ctxt).level in + let level_after = Raw_level_repr.add level_0 challenge_window in + lift + @@ let* (rollup, ctxt) = new_sc_rollup ctxt in + let staker1 = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let staker2 = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1RikjCkrEde1QQmuesp796jCxeiyE6t3Vo" + in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker1 in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker2 in + let commitment1 = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level_0 staker1 commitment1 + in + let commitment2 = + Sc_rollup_repr.Commitment. + { + predecessor = c1; + inbox_level = Raw_level_repr.of_int32_exn 41l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (_node, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level_0 staker2 commitment2 + in + let* ctxt = + Sc_rollup_storage.cement_commitment ctxt rollup level_after c1 + in + assert_true ctxt + +let test_can_remove_staker () = + let* ctxt = new_context () in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let level_0 = (Raw_context.current_level ctxt).level in + let level_after = Raw_level_repr.add level_0 challenge_window in + lift + @@ let* (rollup, ctxt) = new_sc_rollup ctxt in + let staker1 = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let staker2 = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1RikjCkrEde1QQmuesp796jCxeiyE6t3Vo" + in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker1 in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker2 in + let commitment1 = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level_0 staker1 commitment1 + in + let commitment2 = + Sc_rollup_repr.Commitment. + { + predecessor = c1; + inbox_level = Raw_level_repr.of_int32_exn 41l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (_node, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level_0 staker2 commitment2 + in + let* ctxt = Sc_rollup_storage.remove_staker ctxt rollup staker1 in + let* ctxt = + Sc_rollup_storage.cement_commitment ctxt rollup level_after c1 + in + assert_true ctxt + +let test_can_remove_staker2 () = + let* ctxt = new_context () in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let level_0 = (Raw_context.current_level ctxt).level in + let level_after = Raw_level_repr.add level_0 challenge_window in + lift + @@ let* (rollup, ctxt) = new_sc_rollup ctxt in + let staker1 = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let staker2 = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1RikjCkrEde1QQmuesp796jCxeiyE6t3Vo" + in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker1 in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker2 in + let commitment1 = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level_0 staker1 commitment1 + in + let commitment2 = + Sc_rollup_repr.Commitment. + { + predecessor = c1; + inbox_level = Raw_level_repr.of_int32_exn 41l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (_node, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level_0 staker2 commitment2 + in + let* ctxt = Sc_rollup_storage.remove_staker ctxt rollup staker2 in + let* ctxt = + Sc_rollup_storage.cement_commitment ctxt rollup level_after c1 + in + assert_true ctxt + +let test_removed_staker_can_not_withdraw () = + let* ctxt = new_context () in + let level_0 = (Raw_context.current_level ctxt).level in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker1 = + Sc_rollup_repr.Staker.of_b58check_exn "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let staker2 = + Sc_rollup_repr.Staker.of_b58check_exn "tz1RikjCkrEde1QQmuesp796jCxeiyE6t3Vo" + in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker1 in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker2 in + let commitment1 = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + lift + @@ Sc_rollup_storage.refine_stake ctxt rollup level_0 staker1 commitment1 + in + let commitment2 = + Sc_rollup_repr.Commitment. + { + predecessor = c1; + inbox_level = Raw_level_repr.of_int32_exn 41l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (_node, ctxt) = + lift + @@ Sc_rollup_storage.refine_stake ctxt rollup level_0 staker2 commitment2 + in + let* ctxt = lift @@ Sc_rollup_storage.remove_staker ctxt rollup staker2 in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.withdraw_stake ctxt rollup staker2) + "Unknown staker." + +let test_no_cement_on_conflict () = + let* ctxt = new_context () in + let level_0 = (Raw_context.current_level ctxt).level in + let level_after = Raw_level_repr.add level_0 5000 in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker1 = + Sc_rollup_repr.Staker.of_b58check_exn "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let staker2 = + Sc_rollup_repr.Staker.of_b58check_exn "tz1RikjCkrEde1QQmuesp796jCxeiyE6t3Vo" + in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker1 in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker2 in + let commitment1 = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + lift + @@ Sc_rollup_storage.refine_stake ctxt rollup level_0 staker1 commitment1 + in + let commitment2 = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 44l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (_node, ctxt) = + lift + @@ Sc_rollup_storage.refine_stake ctxt rollup level_0 staker2 commitment2 + in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_storage.cement_commitment ctxt rollup level_after c1) + "Attempted to cement a disputed commitment." + +let test_finds_conflict_point_at_lcc () = + let* ctxt = new_context () in + let level_0 = (Raw_context.current_level ctxt).level in + lift + @@ let* (rollup, ctxt) = new_sc_rollup ctxt in + let staker1 = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let staker2 = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1RikjCkrEde1QQmuesp796jCxeiyE6t3Vo" + in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker1 in + let* ctxt = Sc_rollup_storage.deposit_stake ctxt rollup staker2 in + let commitment1 = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level_0 staker1 commitment1 + in + let commitment2 = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 55l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c2, ctxt) = + Sc_rollup_storage.refine_stake ctxt rollup level_0 staker2 commitment2 + in + let* ((left, right), ctxt) = + Sc_rollup_storage.get_conflict_point ctxt rollup staker1 staker2 + in + if left = c1 && right = c2 then assert_true ctxt else assert false + +let tests = + [ + Tztest.tztest + "deposit to missing rollup fails" + `Quick + test_deposit_to_missing_rollup; + Tztest.tztest + "deposit to existing rollup" + `Quick + test_deposit_to_existing_rollup; + Tztest.tztest "can not deposit twice" `Quick test_can_not_stake_twice; + Tztest.tztest "deposit, then withdraw" `Quick test_deposit_then_withdraw; + Tztest.tztest + "cement with zero stakers fails" + `Quick + test_cement_with_zero_stakers_fails; + Tztest.tztest + "withdrawing when not staked fails" + `Quick + test_withdraw_when_not_staked; + Tztest.tztest "withdrawing twice fails" `Quick test_withdrawing_twice; + Tztest.tztest "stake on new node" `Quick test_deposit_then_refine; + Tztest.tztest "stake on existing node" `Quick test_stake_on_existing_node; + Tztest.tztest + "withdrawal fails when not staked on LCC" + `Quick + test_withdrawal_fails_when_not_staked_on_lcc; + Tztest.tztest + "rollup starts in pre-boot state" + `Quick + test_initial_state_is_pre_boot; + Tztest.tztest "cement" `Quick test_cement; + Tztest.tztest + "cement unknown commitment fails" + `Quick + test_cement_unknown_commitment_fails; + Tztest.tztest + "cement fails when too recent" + `Quick + test_cement_fail_too_recent; + Tztest.tztest + "cement deadline uses oldest add time" + `Quick + test_cement_deadline_uses_oldest_add_time; + Tztest.tztest "cement with two stakers" `Quick test_cement_with_two_stakers; + Tztest.tztest "no cement on conflict" `Quick test_no_cement_on_conflict; + Tztest.tztest + "finds conflict point at LCC" + `Quick + test_finds_conflict_point_at_lcc; + Tztest.tztest "can remove staker 1" `Quick test_can_remove_staker; + Tztest.tztest "can remove staker 2" `Quick test_can_remove_staker2; + Tztest.tztest + "removed staker can not withdraw" + `Quick + test_removed_staker_can_not_withdraw; + Tztest.tztest + "removing staker from the LCC fails" + `Quick + test_removing_staker_from_lcc_fails; + ] + +(* FIXME: https://gitlab.com/tezos/tezos/-/issues/2460 + Further tests to be added. + *) diff --git a/tests_python/tests_alpha/test_mockup.py b/tests_python/tests_alpha/test_mockup.py index f0534997e661a54efe6120336b7be44a9b76232c..898c14468101a26915e6d504d5125dc8b35edb11 100644 --- a/tests_python/tests_alpha/test_mockup.py +++ b/tests_python/tests_alpha/test_mockup.py @@ -667,6 +667,7 @@ def _test_create_mockup_init_show_roundtrip( "tx_rollup_max_finalized_levels": 60_100, "sc_rollup_enable": False, "sc_rollup_origination_size": 6_314, + "sc_rollup_challenge_window_in_blocks": 20_160, } ), ], diff --git a/tezt/_regressions/rpc/alpha.client.others.out b/tezt/_regressions/rpc/alpha.client.others.out index 97ccb4324fc1fb44f123d62dbe1f2a277c9c4eb3..ba18c16661f4d9951d01fa64e4abe32414b0cba8 100644 --- a/tezt/_regressions/rpc/alpha.client.others.out +++ b/tezt/_regressions/rpc/alpha.client.others.out @@ -37,7 +37,8 @@ tezt/_regressions/rpc/alpha.client.others.out "tx_rollup_max_unfinalized_levels": 2100, "tx_rollup_max_messages_per_inbox": 1010, "tx_rollup_max_finalized_levels": 60100, "sc_rollup_enable": false, - "sc_rollup_origination_size": 6314 } + "sc_rollup_origination_size": 6314, + "sc_rollup_challenge_window_in_blocks": 20160 } ./tezos-client rpc get /chains/main/blocks/head/helpers/baking_rights [ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", diff --git a/tezt/_regressions/rpc/alpha.light.others.out b/tezt/_regressions/rpc/alpha.light.others.out index 721ba3a507d5fcbb5a1b4e5ca39df70484ae7829..6f2fce1a2b6b47790bac4016c5112cf2dc31d908 100644 --- a/tezt/_regressions/rpc/alpha.light.others.out +++ b/tezt/_regressions/rpc/alpha.light.others.out @@ -38,7 +38,8 @@ protocol of light mode unspecified, using the node's protocol: ProtoGenesisGenes "tx_rollup_max_unfinalized_levels": 2100, "tx_rollup_max_messages_per_inbox": 1010, "tx_rollup_max_finalized_levels": 60100, "sc_rollup_enable": false, - "sc_rollup_origination_size": 6314 } + "sc_rollup_origination_size": 6314, + "sc_rollup_challenge_window_in_blocks": 20160 } ./tezos-client --mode light rpc get /chains/main/blocks/head/helpers/baking_rights protocol of light mode unspecified, using the node's protocol: ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im diff --git a/tezt/_regressions/rpc/alpha.proxy.others.out b/tezt/_regressions/rpc/alpha.proxy.others.out index 246dd8176d4f8d537e75740bc52df94e9cde08d4..ba5866eb6db15de4973327bcf9b064e180fd6afa 100644 --- a/tezt/_regressions/rpc/alpha.proxy.others.out +++ b/tezt/_regressions/rpc/alpha.proxy.others.out @@ -38,7 +38,8 @@ protocol of proxy unspecified, using the node's protocol: ProtoGenesisGenesisGen "tx_rollup_max_unfinalized_levels": 2100, "tx_rollup_max_messages_per_inbox": 1010, "tx_rollup_max_finalized_levels": 60100, "sc_rollup_enable": false, - "sc_rollup_origination_size": 6314 } + "sc_rollup_origination_size": 6314, + "sc_rollup_challenge_window_in_blocks": 20160 } ./tezos-client --mode proxy rpc get /chains/main/blocks/head/helpers/baking_rights protocol of proxy unspecified, using the node's protocol: ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im diff --git a/tezt/_regressions/rpc/alpha.proxy_server.others.out b/tezt/_regressions/rpc/alpha.proxy_server.others.out index 3084bc9e14db9ca3c592d8e519f77a90fc72cf05..a9790cb4470335b06361b79d0842e0d7d39c18aa 100644 --- a/tezt/_regressions/rpc/alpha.proxy_server.others.out +++ b/tezt/_regressions/rpc/alpha.proxy_server.others.out @@ -37,7 +37,8 @@ tezt/_regressions/rpc/alpha.proxy_server.others.out "tx_rollup_max_unfinalized_levels": 2100, "tx_rollup_max_messages_per_inbox": 1010, "tx_rollup_max_finalized_levels": 60100, "sc_rollup_enable": false, - "sc_rollup_origination_size": 6314 } + "sc_rollup_origination_size": 6314, + "sc_rollup_challenge_window_in_blocks": 20160 } ./tezos-client rpc get /chains/main/blocks/head/helpers/baking_rights [ { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", diff --git a/tezt/_regressions/sc_rollup_node_configuration.out b/tezt/_regressions/sc_rollup_node_configuration.out index 4090175471b0cc7787b16425508702d78fe69e7f..c88ebcfd80f5d3e3d861efa976d002afee7dd5e1 100644 --- a/tezt/_regressions/sc_rollup_node_configuration.out +++ b/tezt/_regressions/sc_rollup_node_configuration.out @@ -1,2 +1,2 @@ tezt/_regressions/sc_rollup_node_configuration.out -{"sc-rollup-address":"scr1YrJSFLQkZrLtE6m5pEogVP1zf4WGNiwo1"} +{"sc-rollup-address":"scr1Yw3y3iekKyKiHWgvWQVfz3YeY3dQBwFvG"} diff --git a/tezt/_regressions/sc_rollup_origination.out b/tezt/_regressions/sc_rollup_origination.out index dd6b837fadf90147e64263e0e29f87aa5d350699..5c6aef42c2a5d82d91d3440324aff698c0d50c8e 100644 --- a/tezt/_regressions/sc_rollup_origination.out +++ b/tezt/_regressions/sc_rollup_origination.out @@ -1,2 +1,2 @@ tezt/_regressions/sc_rollup_origination.out -scr1YrJSFLQkZrLtE6m5pEogVP1zf4WGNiwo1 +scr1Yw3y3iekKyKiHWgvWQVfz3YeY3dQBwFvG diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 40b145c1495e16223d2123c87a4a8eedcd83b891..ba5779dcda7af8beafc0f8c4684a44b5db72cd32 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -23,6 +23,12 @@ (* *) (*****************************************************************************) +(* Testing + ------- + Component: Smart Contract Optimistic Rollups + Invocation: dune exec tezt/tests/main.exe -- --file sc_rollup.ml +*) + (* Helpers