From 53ce420fd7dfb29a89bedf4ad69fde8e578ab4ea Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Tue, 26 Nov 2024 10:50:33 +0100 Subject: [PATCH 1/5] Alpha/DAL: add Dal_incentives_disabled error --- src/proto_alpha/lib_protocol/alpha_context.mli | 3 +++ src/proto_alpha/lib_protocol/dal_errors_repr.ml | 12 ++++++++++++ src/proto_alpha/lib_protocol/raw_context.ml | 6 ++++++ src/proto_alpha/lib_protocol/raw_context.mli | 7 ++++++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index d62c18b0ce6c..dc25a2b6a03b 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2765,6 +2765,8 @@ module Dal : sig val only_if_feature_enabled : t -> default:(t -> 'a) -> (t -> 'a) -> 'a + val assert_incentives_enabled : t -> unit tzresult + val only_if_incentives_enabled : t -> default:(t -> 'a) -> (t -> 'a) -> 'a (** This module re-exports definitions from {!Dal_slot_index_repr}. *) @@ -3016,6 +3018,7 @@ module Dal_errors : sig from Dal_slot_repr or Dal_attestation_repr. *) type error += | Dal_feature_disabled + | Dal_incentives_disabled | Dal_slot_index_above_hard_limit of {given : int; limit : int} | Dal_publish_commitment_invalid_index of { given : Dal.Slot_index.t; diff --git a/src/proto_alpha/lib_protocol/dal_errors_repr.ml b/src/proto_alpha/lib_protocol/dal_errors_repr.ml index 585b9b6f78cc..2645f9a25d29 100644 --- a/src/proto_alpha/lib_protocol/dal_errors_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_errors_repr.ml @@ -25,6 +25,7 @@ type error += | Dal_feature_disabled + | Dal_incentives_disabled | Dal_slot_index_above_hard_limit of {given : int; limit : int} | Dal_publish_commitment_invalid_index of { given : Dal_slot_index_repr.t; @@ -65,6 +66,17 @@ let () = (function Dal_feature_disabled -> Some () | _ -> None) (fun () -> Dal_feature_disabled) ; + let description = "Incentives for the DAL are not yet enabled." in + register_error_kind + `Permanent + ~id:"operation.dal_incentives_disabled" + ~title:"DAL incentives are disabled" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Dal_incentives_disabled -> Some () | _ -> None) + (fun () -> Dal_incentives_disabled) ; + let description = "Slot index above hard limit" in register_error_kind `Permanent diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index 3f5b46fc2710..2a5ec0027844 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -2223,6 +2223,12 @@ module Dal = struct let constants = constants ctxt in if constants.dal.feature_enable then f ctxt else default ctxt + let assert_incentives_enabled ctxt = + let constants = constants ctxt in + error_unless + Compare.Bool.(constants.dal.incentives_enable = true) + Dal_errors_repr.Dal_incentives_disabled + let only_if_incentives_enabled ctxt ~default f = let constants = constants ctxt in if constants.dal.incentives_enable then f ctxt else default ctxt diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index e98c2376864f..e496b8d2ee97 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -470,13 +470,18 @@ module Dal : sig Dal_slot_index_repr.t -> Dal_attestation_repr.Accountability.attestation_status - (* Check whether the DAL feature flag is set and return an error if not. *) + (* Check whether the DAL feature flag is set and return the error + {!Dal_feature_disabled} if not. *) val assert_feature_enabled : t -> unit tzresult (* [only_if_dal_feature_enabled ctxt ~default f] executes [f ctxt] if the DAL feature flag is enabled and otherwise [default ctxt]. *) val only_if_feature_enabled : t -> default:(t -> 'a) -> (t -> 'a) -> 'a + (* Check whether the DAL incentives flag is set and return the error + {!Dal_incentives_disabled} if not. *) + val assert_incentives_enabled : t -> unit tzresult + (* [only_if_dal_incentives_enabled ctxt ~default f] executes [f ctxt] if the DAL incentives flag is enabled and otherwise [default ctxt]. *) val only_if_incentives_enabled : t -> default:(t -> 'a) -> (t -> 'a) -> 'a -- GitLab From 07bd4fd6aa121c1851146acf0a2607414e049ef9 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Thu, 3 Oct 2024 11:30:18 +0200 Subject: [PATCH 2/5] Alpha/DAL: add new module Dal.Shard_with_proof --- .../lib_protocol/alpha_context.mli | 6 ++ src/proto_alpha/lib_protocol/dal_slot_repr.ml | 66 +++++++++++++++++-- .../lib_protocol/dal_slot_repr.mli | 15 ++++- 3 files changed, 79 insertions(+), 8 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index dc25a2b6a03b..09574b3f7c5d 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2926,6 +2926,12 @@ module Dal : sig context -> number_of_slots:int -> (context * Attestation.t) tzresult Lwt.t end + module Shard_with_proof : sig + type t = {shard : Dal.shard; proof : Dal.shard_proof} + + val verify : cryptobox -> Slot.Commitment.t -> t -> unit tzresult + end + module Operations : sig module Publish_commitment : sig type t = { diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index aea65d068c79..b1d7b071c3a8 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -118,6 +118,57 @@ end module Slot_index = Dal_slot_index_repr +module Shard_with_proof = struct + type t = {shard : Dal.shard; proof : Dal.shard_proof} + + let encoding = + let open Data_encoding in + conv + (fun {shard; proof} -> (shard, proof)) + (fun (shard, proof) -> {shard; proof}) + (obj2 + (req "shard" Dal.shard_encoding) + (req "proof" Dal.shard_proof_encoding)) + + type error += Dal_shard_proof_error of string + + let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"dal_slot_repr.shard_with_proof.dal_shard_proof_error" + ~title:"DAL shard proof error" + ~description:"An error occurred while validating the DAL shard proof." + ~pp:(fun ppf e -> Format.fprintf ppf "DAL shard proof error: %s" e) + (obj1 (req "error" (string Plain))) + (function Dal_shard_proof_error e -> Some e | _ -> None) + (fun e -> Dal_shard_proof_error e) + + let dal_proof_error reason = Dal_shard_proof_error reason + + let proof_error reason = error @@ dal_proof_error reason + + let verify cryptobox commitment t = + let open Result_syntax in + let fail_with_error_msg what = + Format.kasprintf + proof_error + "%s (for commitment = %a)." + what + Commitment.pp + commitment + in + match Dal.verify_shard cryptobox commitment t.shard t.proof with + | Ok () -> return () + | Error `Invalid_shard -> fail_with_error_msg "Invalid shard" + | Error (`Invalid_degree_strictly_less_than_expected _) -> + fail_with_error_msg "Invalid_degree_strictly_less_than_expected" + | Error `Shard_length_mismatch -> + fail_with_error_msg "Shard_length_mismatch" + | Error (`Shard_index_out_of_range str) -> + fail_with_error_msg ("Shard_index_out_of_range (" ^ str ^ ")") +end + module Page = struct type content = Bytes.t @@ -1053,7 +1104,7 @@ module History = struct inc_proof) type error += - | Dal_proof_error of string + | Dal_page_proof_error of string | Unexpected_page_size of {expected_size : int; page_size : int} let () = @@ -1061,12 +1112,13 @@ module History = struct register_error_kind `Permanent ~id:"dal_slot_repr.slots_history.dal_proof_error" - ~title:"Dal proof error" - ~description:"Error occurred during Dal proof production or validation" - ~pp:(fun ppf e -> Format.fprintf ppf "Dal proof error: %s" e) + ~title:"DAL page proof error" + ~description: + "Error occurred during DAL page proof production or validation" + ~pp:(fun ppf e -> Format.fprintf ppf "DAL page proof error: %s" e) (obj1 (req "error" (string Plain))) - (function Dal_proof_error e -> Some e | _ -> None) - (fun e -> Dal_proof_error e) + (function Dal_page_proof_error e -> Some e | _ -> None) + (fun e -> Dal_page_proof_error e) let () = let open Data_encoding in @@ -1091,7 +1143,7 @@ module History = struct (fun (expected_size, page_size) -> Unexpected_page_size {expected_size; page_size}) - let dal_proof_error reason = Dal_proof_error reason + let dal_proof_error reason = Dal_page_proof_error reason let proof_error reason = error @@ dal_proof_error reason diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index ab893aa0b8bc..d60e76529f23 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -135,6 +135,19 @@ module Header : sig Dal.t -> Commitment.t -> Commitment_proof.t -> bool tzresult end +module Shard_with_proof : sig + type t = {shard : Dal.shard; proof : Dal.shard_proof} + + type error += Dal_shard_proof_error of string + + val encoding : t Data_encoding.t + + (* [verify cryptobox commitment t] verifies the shard proof from [t] against + the shard in [t] and the provided [commitment]. Returns + [Dal_shard_proof_error] if the verification fails. *) + val verify : Dal.t -> Commitment.t -> t -> unit tzresult +end + (** A DAL slot is decomposed to a successive list of pages with fixed content size. The size is chosen so that it's possible to inject a page in a Tezos L1 operation if needed during the proof phase of a refutation game. @@ -437,7 +450,7 @@ module History : sig type error += Add_element_in_slots_skip_list_violates_ordering type error += - | Dal_proof_error of string + | Dal_page_proof_error of string | Unexpected_page_size of {expected_size : int; page_size : int} module Internal_for_tests : sig -- GitLab From 4a37775e34ec15731e7cfd64084c63cae0dadda5 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Thu, 3 Oct 2024 11:31:01 +0200 Subject: [PATCH 3/5] Alpha/DAL: add new anonymous operation Dal_entrapment_evidence Weights and conflicts are defined in a follow-up commit. --- .../lib_client/operation_result.ml | 13 +++++ .../lib_injector/injector_plugin.ml | 1 + src/proto_alpha/lib_plugin/RPC.ml | 8 +++ src/proto_alpha/lib_plugin/mempool.ml | 5 +- .../lib_protocol/alpha_context.mli | 8 +++ src/proto_alpha/lib_protocol/apply.ml | 9 ++- src/proto_alpha/lib_protocol/apply_results.ml | 7 +++ .../lib_protocol/apply_results.mli | 4 ++ .../lib_protocol/operation_repr.ml | 56 ++++++++++++++----- .../lib_protocol/operation_repr.mli | 21 +++++-- .../lib_protocol/test/helpers/block.ml | 1 + .../lib_protocol/test/helpers/dal_helpers.ml | 8 +-- .../validate/generator_descriptors.ml | 15 +++++ .../validate/generator_descriptors.mli | 1 + .../test/integration/validate/test_sanity.ml | 2 + .../test/unit/test_dal_slot_proof.ml | 4 +- src/proto_alpha/lib_protocol/validate.ml | 20 +++++++ .../lib_sc_rollup_node/sc_rollup_injector.ml | 1 + 18 files changed, 157 insertions(+), 27 deletions(-) diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index 5041035e76b4..d918565a9af6 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -1063,6 +1063,19 @@ let pp_contents_and_result : forbidden_delegate pp_balance_updates balance_updates + | ( Dal_entrapment_evidence + {attestation; slot_index = _; shard_with_proof = _}, + Dal_entrapment_evidence_result {balance_updates} ) -> + Format.fprintf + ppf + "@[Dal entrapment evidence:@,\ + attestation: %a@,\ + Balance updates:@,\ + \ %a@]" + Operation_hash.pp + (Operation.hash attestation) + pp_balance_updates + balance_updates | Activate_account {id; _}, Activate_account_result bus -> Format.fprintf ppf diff --git a/src/proto_alpha/lib_injector/injector_plugin.ml b/src/proto_alpha/lib_injector/injector_plugin.ml index 3b3134a43a37..6d8b121028dd 100644 --- a/src/proto_alpha/lib_injector/injector_plugin.ml +++ b/src/proto_alpha/lib_injector/injector_plugin.ml @@ -159,6 +159,7 @@ module Proto_client = struct | Double_attestation_evidence_result _ -> Successful | Double_preattestation_evidence_result _ -> Successful | Double_baking_evidence_result _ -> Successful + | Dal_entrapment_evidence_result _ -> Successful | Activate_account_result _ -> Successful | Proposals_result -> Successful | Ballot_result -> Successful diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index 7917238a2667..781a559316b0 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -3367,6 +3367,14 @@ module Forge = struct let double_preattestation_evidence ctxt block ~branch ~op1 ~op2 () = operation ctxt block ~branch (Double_preattestation_evidence {op1; op2}) + let dal_entrapment_evidence ctxt block ~branch ~attestation ~slot_index + ~shard_with_proof = + operation + ctxt + block + ~branch + (Dal_entrapment_evidence {attestation; slot_index; shard_with_proof}) + let empty_proof_of_work_nonce = Bytes.make Constants_repr.proof_of_work_nonce_size '\000' diff --git a/src/proto_alpha/lib_plugin/mempool.ml b/src/proto_alpha/lib_plugin/mempool.ml index bc4dacf05049..706ab10a65e3 100644 --- a/src/proto_alpha/lib_plugin/mempool.ml +++ b/src/proto_alpha/lib_plugin/mempool.ml @@ -556,6 +556,7 @@ let pre_filter info config | Single (Double_preattestation_evidence _) | Single (Double_attestation_evidence _) | Single (Double_baking_evidence _) + | Single (Dal_entrapment_evidence _) | Single (Activate_account _) | Single (Proposals _) | Single (Vdf_revelation _) @@ -692,7 +693,8 @@ let find_manager {shell = _; protocol_data = Operation_data {contents; _}} = ( Preattestation _ | Attestation _ | Proposals _ | Ballot _ | Seed_nonce_revelation _ | Vdf_revelation _ | Double_baking_evidence _ | Double_preattestation_evidence _ | Double_attestation_evidence _ - | Activate_account _ | Drain_delegate _ | Failing_noop _ ) -> + | Dal_entrapment_evidence _ | Activate_account _ | Drain_delegate _ + | Failing_noop _ ) -> None (* The purpose of this module is to offer a version of @@ -814,6 +816,7 @@ let sources_from_operation ctxt | Single (Double_preattestation_evidence _) | Single (Double_attestation_evidence _) | Single (Double_baking_evidence _) + | Single (Dal_entrapment_evidence _) | Single (Activate_account _) | Single (Vdf_revelation _) -> return_nil diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 09574b3f7c5d..9adb9ef38f69 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -4481,6 +4481,8 @@ module Kind : sig type double_baking_evidence = Double_baking_evidence_kind + type dal_entrapment_evidence = Dal_entrapment_evidence_kind + type activate_account = Activate_account_kind type proposals = Proposals_kind @@ -4631,6 +4633,12 @@ and _ contents = bh2 : Block_header.t; } -> Kind.double_baking_evidence contents + | Dal_entrapment_evidence : { + attestation : Kind.attestation operation; + slot_index : Dal.Slot_index.t; + shard_with_proof : Dal.Shard_with_proof.t; + } + -> Kind.dal_entrapment_evidence contents | Activate_account : { id : Ed25519.Public_key_hash.t; activation_code : Blinded_public_key_hash.activation_code; diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index abed82e53e02..32ccb0038447 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2204,7 +2204,8 @@ let record_operation (type kind) ctxt hash (operation : kind operation) : ( Failing_noop _ | Proposals _ | Ballot _ | Seed_nonce_revelation _ | Vdf_revelation _ | Double_attestation_evidence _ | Double_preattestation_evidence _ | Double_baking_evidence _ - | Activate_account _ | Drain_delegate _ | Manager_operation _ ) + | Dal_entrapment_evidence _ | Activate_account _ | Drain_delegate _ + | Manager_operation _ ) | Cons (Manager_operation _, _) -> record_non_consensus_operation_hash ctxt hash @@ -2479,6 +2480,12 @@ let apply_contents_list (type kind) ctxt chain_id (mode : mode) ~payload_producer | Single (Double_baking_evidence {bh1; bh2 = _}) -> punish_double_baking ctxt ~operation_hash bh1 ~payload_producer + | Single (Dal_entrapment_evidence _) -> + (* This should be unreachable, because this operation is not yet valid. *) + return + ( ctxt, + Single_result (Dal_entrapment_evidence_result {balance_updates = []}) + ) | Single (Activate_account {id = pkh; activation_code}) -> let blinded_pkh = Blinded_public_key_hash.of_ed25519_pkh activation_code pkh diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index 13e0ea69772a..cc8b50b624f7 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -908,6 +908,10 @@ type 'kind contents_result = balance_updates : Receipt.balance_updates; } -> Kind.double_baking_evidence contents_result + | Dal_entrapment_evidence_result : { + balance_updates : Receipt.balance_updates; + } + -> Kind.dal_entrapment_evidence contents_result | Activate_account_result : Receipt.balance_updates -> Kind.activate_account contents_result @@ -1378,6 +1382,7 @@ module Encoding = struct | Contents_result (Double_attestation_evidence_result _) -> None | Contents_result (Double_preattestation_evidence_result _) -> None | Contents_result (Double_baking_evidence_result _) -> None + | Contents_result (Dal_entrapment_evidence_result _) -> None | Contents_result (Activate_account_result _) -> None | Contents_result (Drain_delegate_result _) -> None | Contents_result Proposals_result -> None); @@ -1839,6 +1844,8 @@ let kind_equal : | Double_attestation_evidence _, _ -> None | Double_baking_evidence _, Double_baking_evidence_result _ -> Some Eq | Double_baking_evidence _, _ -> None + | Dal_entrapment_evidence _, Dal_entrapment_evidence_result _ -> Some Eq + | Dal_entrapment_evidence _, _ -> None | Activate_account _, Activate_account_result _ -> Some Eq | Activate_account _, _ -> None | Proposals _, Proposals_result -> Some Eq diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index 36bd8e59790d..2828fe10c6c0 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -94,6 +94,10 @@ and 'kind contents_result = balance_updates : Receipt.balance_updates; } -> Kind.double_baking_evidence contents_result + | Dal_entrapment_evidence_result : { + balance_updates : Receipt.balance_updates; + } + -> Kind.dal_entrapment_evidence contents_result | Activate_account_result : Receipt.balance_updates -> Kind.activate_account contents_result diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index 301e0370d9cc..9886d8332c8f 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -55,6 +55,8 @@ module Kind = struct type double_baking_evidence = Double_baking_evidence_kind + type dal_entrapment_evidence = Dal_entrapment_evidence_kind + type activate_account = Activate_account_kind type proposals = Proposals_kind @@ -260,6 +262,12 @@ and _ contents = bh2 : Block_header_repr.t; } -> Kind.double_baking_evidence contents + | Dal_entrapment_evidence : { + attestation : Kind.attestation operation; + slot_index : Dal_slot_index_repr.t; + shard_with_proof : Dal_slot_repr.Shard_with_proof.t; + } + -> Kind.dal_entrapment_evidence contents | Activate_account : { id : Ed25519.Public_key_hash.t; activation_code : Blinded_public_key_hash.activation_code; @@ -1728,6 +1736,7 @@ let acceptable_pass (op : packed_operation) = | Single (Double_attestation_evidence _) -> Some anonymous_pass | Single (Double_preattestation_evidence _) -> Some anonymous_pass | Single (Double_baking_evidence _) -> Some anonymous_pass + | Single (Dal_entrapment_evidence _) -> Some anonymous_pass | Single (Activate_account _) -> Some anonymous_pass | Single (Drain_delegate _) -> Some anonymous_pass | Single (Manager_operation _) -> Some manager_pass @@ -1816,7 +1825,8 @@ let check_signature (type kind) key chain_id (op : kind operation) = ( Failing_noop _ | Proposals _ | Ballot _ | Seed_nonce_revelation _ | Vdf_revelation _ | Double_attestation_evidence _ | Double_preattestation_evidence _ | Double_baking_evidence _ - | Activate_account _ | Drain_delegate _ | Manager_operation _ ) -> + | Dal_entrapment_evidence _ | Activate_account _ | Drain_delegate _ + | Manager_operation _ ) -> Generic_operation | Cons (Manager_operation _, _ops) -> Generic_operation in @@ -1907,6 +1917,8 @@ let equal_contents_kind : type a b. a contents -> b contents -> (a, b) eq option | Double_preattestation_evidence _, _ -> None | Double_baking_evidence _, Double_baking_evidence _ -> Some Eq | Double_baking_evidence _, _ -> None + | Dal_entrapment_evidence _, Dal_entrapment_evidence _ -> Some Eq + | Dal_entrapment_evidence _, _ -> None | Activate_account _, Activate_account _ -> Some Eq | Activate_account _, _ -> None | Proposals _, Proposals _ -> Some Eq @@ -2137,6 +2149,10 @@ type _ weight = | Weight_double_preattestation : round_infos -> anonymous_pass_type weight | Weight_double_attestation : round_infos -> anonymous_pass_type weight | Weight_double_baking : double_baking_infos -> anonymous_pass_type weight + | Weight_dal_entrapment_evidence : + (* TODO: to be refined in the next commit *) + unit + -> anonymous_pass_type weight | Weight_activate_account : Ed25519.Public_key_hash.t -> anonymous_pass_type weight @@ -2251,6 +2267,8 @@ let weight_of : packed_operation -> operation_weight = consensus_infos_and_hash_from_block_header bh1 in W (Anonymous, Weight_double_baking double_baking_infos) + | Single (Dal_entrapment_evidence _) -> + W (Anonymous, Weight_dal_entrapment_evidence ()) | Single (Activate_account {id; _}) -> W (Anonymous, Weight_activate_account id) | Single (Drain_delegate {delegate; _}) -> @@ -2404,11 +2422,10 @@ let compare_vote_weight w1 w2 = Two {!Activate_account} are compared as their [id]. - When comparing different kind of anonymous operations, the order is - as follows: {!Double_preattestation_evidence} > - {!Double_attestation_evidence} > {!Double_baking_evidence} > - {!Vdf_revelation} > {!Seed_nonce_revelation} > {!Activate_account}. - *) + When comparing different kind of anonymous operations, the order is as + follows: {!Double_preattestation_evidence} > {!Double_attestation_evidence} > + {!Double_baking_evidence} > {!Dal_entrapment_evidence} > {!Vdf_revelation} > + {!Seed_nonce_revelation} > {!Activate_account}. *) let compare_anonymous_weight w1 w2 = match (w1, w2) with | Weight_double_preattestation infos1, Weight_double_preattestation infos2 -> @@ -2421,23 +2438,34 @@ let compare_anonymous_weight w1 w2 = if Compare.Int.(cmp <> 0) then cmp else -1 | Weight_double_attestation infos1, Weight_double_attestation infos2 -> compare_round_infos infos1 infos2 - | ( ( Weight_double_baking _ | Weight_seed_nonce_revelation _ - | Weight_vdf_revelation _ | Weight_activate_account _ - | Weight_drain_delegate _ ), + | ( ( Weight_double_baking _ | Weight_dal_entrapment_evidence _ + | Weight_seed_nonce_revelation _ | Weight_vdf_revelation _ + | Weight_activate_account _ | Weight_drain_delegate _ ), (Weight_double_preattestation _ | Weight_double_attestation _) ) -> -1 | ( (Weight_double_preattestation _ | Weight_double_attestation _), - ( Weight_double_baking _ | Weight_seed_nonce_revelation _ - | Weight_vdf_revelation _ | Weight_activate_account _ - | Weight_drain_delegate _ ) ) -> + ( Weight_double_baking _ | Weight_dal_entrapment_evidence _ + | Weight_seed_nonce_revelation _ | Weight_vdf_revelation _ + | Weight_activate_account _ | Weight_drain_delegate _ ) ) -> 1 | Weight_double_baking infos1, Weight_double_baking infos2 -> compare_baking_infos infos1 infos2 - | ( ( Weight_seed_nonce_revelation _ | Weight_vdf_revelation _ - | Weight_activate_account _ | Weight_drain_delegate _ ), + | ( ( Weight_dal_entrapment_evidence _ | Weight_seed_nonce_revelation _ + | Weight_vdf_revelation _ | Weight_activate_account _ + | Weight_drain_delegate _ ), Weight_double_baking _ ) -> -1 | ( Weight_double_baking _, + ( Weight_dal_entrapment_evidence _ | Weight_seed_nonce_revelation _ + | Weight_vdf_revelation _ | Weight_activate_account _ + | Weight_drain_delegate _ ) ) -> + 1 + | Weight_dal_entrapment_evidence (), Weight_dal_entrapment_evidence () -> 0 + | ( ( Weight_seed_nonce_revelation _ | Weight_vdf_revelation _ + | Weight_activate_account _ | Weight_drain_delegate _ ), + Weight_dal_entrapment_evidence _ ) -> + -1 + | ( Weight_dal_entrapment_evidence (), ( Weight_seed_nonce_revelation _ | Weight_vdf_revelation _ | Weight_activate_account _ | Weight_drain_delegate _ ) ) -> 1 diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index f8052915800c..b92ac2f13291 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -33,6 +33,7 @@ - double baking evidence - double preattestation evidence - double attestation evidence + - DAL entrapment evidence - seed nonce revelation - account activation - proposal (see: [Voting_repr]) @@ -89,6 +90,8 @@ module Kind : sig type double_baking_evidence = Double_baking_evidence_kind + type dal_entrapment_evidence = Dal_entrapment_evidence_kind + type activate_account = Activate_account_kind type proposals = Proposals_kind @@ -289,6 +292,14 @@ and _ contents = bh2 : Block_header_repr.t; } -> Kind.double_baking_evidence contents + (* The attester failed to correctly identify a trap when attesting DAL + slots. *) + | Dal_entrapment_evidence : { + attestation : Kind.attestation operation; + slot_index : Dal_slot_index_repr.t; + shard_with_proof : Dal_slot_repr.Shard_with_proof.t; + } + -> Kind.dal_entrapment_evidence contents (* Activate_account: Account activation allows to register a public key hash on the blockchain. *) | Activate_account : { @@ -587,11 +598,11 @@ val compare_by_passes : packed_operation -> packed_operation -> int The global order is as follows: - {!Attestation} and {!Preattestation} > - {!Proposals} > {!Ballot} > {!Double_preattestation_evidence} > - {!Double_attestation_evidence} > {!Double_baking_evidence} > - {!Vdf_revelation} > {!Seed_nonce_revelation} > {!Activate_account} - > {!Drain_delegate} > {!Manager_operation}. + {!Attestation} and {!Preattestation} > {!Proposals} > {!Ballot} > + {!Double_preattestation_evidence} > {!Double_attestation_evidence} > + {!Double_baking_evidence} > {!Dal_entrapment_evidence} > {!Vdf_revelation} > + {!Seed_nonce_revelation} > {!Activate_account} > {!Drain_delegate} > + {!Manager_operation}. {!Attestation} and {!Preattestation} are compared by the pair of their [level] and [round] such as the farther to the current state [level] and diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index c083d175c837..4c5b1af4990f 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -1145,6 +1145,7 @@ let balance_updates_of_single_content : | Double_attestation_evidence_result {balance_updates; _} | Double_preattestation_evidence_result {balance_updates; _} | Double_baking_evidence_result {balance_updates; _} + | Dal_entrapment_evidence_result {balance_updates; _} | Activate_account_result balance_updates | Drain_delegate_result {balance_updates; _} -> balance_updates diff --git a/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml index 67473e244f76..d0c459b81386 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml @@ -241,7 +241,7 @@ struct let failing_check_produce_result ~__LOC__ ~expected_error res _page_info = Assert.proto_error ~loc:__LOC__ res (fun e -> match (e, expected_error) with - | Hist.Dal_proof_error s, Hist.Dal_proof_error expected -> + | Hist.Dal_page_proof_error s, Hist.Dal_page_proof_error expected -> String.equal s expected | ( Hist.Unexpected_page_size {expected_size = e1; page_size = p1}, Hist.Unexpected_page_size {expected_size = e2; page_size = p2} ) -> @@ -266,7 +266,7 @@ struct failing_check_produce_result ~__LOC__ ~expected_error: - (Hist.Dal_proof_error + (Hist.Dal_page_proof_error "The page ID's slot is confirmed, but no page content and proof are \ provided.") @@ -274,7 +274,7 @@ struct failing_check_produce_result ~__LOC__ ~expected_error: - (Hist.Dal_proof_error + (Hist.Dal_page_proof_error "The page ID's slot is not confirmed, but page content and proof \ are provided.") @@ -282,7 +282,7 @@ struct failing_check_produce_result ~__LOC__ ~expected_error: - (Hist.Dal_proof_error + (Hist.Dal_page_proof_error "Skip_list.search returned Nearest', while all given levels to \ produce proofs are supposed to be in the skip list.") end diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.ml b/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.ml index a6261135a257..0d94f68465ca 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.ml @@ -414,6 +414,17 @@ let double_consensus_descriptor = return (candidates_pre @ candidates_end)); } +let entrapment_descriptor = + let open Lwt_result_syntax in + { + parameters = Fun.id; + required_cycle = (fun _params -> 0); + required_block = (fun _ -> 0); + prelude = (From 0, fun state -> return ([], state)); + opt_prelude = None; + candidates_generator = (fun _state -> return []); + } + let double_baking_descriptor = { parameters = Fun.id; @@ -796,6 +807,7 @@ type op_kind = | KActivate | KDbl_consensus | KDbl_baking + | KEntrapment | KDrain | KManager @@ -809,6 +821,7 @@ let op_kind_of_packed_operation op = | Single (Double_attestation_evidence _) -> KDbl_consensus | Single (Double_preattestation_evidence _) -> KDbl_consensus | Single (Double_baking_evidence _) -> KDbl_baking + | Single (Dal_entrapment_evidence _) -> KEntrapment | Single (Activate_account _) -> KActivate | Single (Proposals _) -> KProposals | Single (Ballot _) -> KBallotExp @@ -832,6 +845,7 @@ let pp_op_kind fmt kind = | KActivate -> "activate_account" | KDbl_consensus -> "double_consensus" | KDbl_baking -> "double_baking" + | KEntrapment -> "dal_entrapment" | KDrain -> "drain_delegate") let descriptor_of ~nb_bootstrap ~max_batch_size = function @@ -846,6 +860,7 @@ let descriptor_of ~nb_bootstrap ~max_batch_size = function | KActivate -> activate_descriptor | KDbl_consensus -> double_consensus_descriptor | KDbl_baking -> double_baking_descriptor + | KEntrapment -> entrapment_descriptor | KDrain -> drain_delegate_descriptor let descriptors_of ~nb_bootstrap ~max_batch_size = diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.mli b/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.mli index f9931fee84e2..f2909c84f996 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.mli +++ b/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.mli @@ -131,6 +131,7 @@ type op_kind = | KActivate | KDbl_consensus | KDbl_baking + | KEntrapment | KDrain | KManager diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/test_sanity.ml b/src/proto_alpha/lib_protocol/test/integration/validate/test_sanity.ml index ca7954b2728b..37bbcd2e90ea 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/test_sanity.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/test_sanity.ml @@ -121,6 +121,8 @@ let covalidation_sanity () = | Single (Double_preattestation_evidence _), _ -> assert false | Single (Double_baking_evidence _), KDbl_baking -> return_unit | Single (Double_baking_evidence _), _ -> assert false + | Single (Dal_entrapment_evidence _), KEntrapment -> return_unit + | Single (Dal_entrapment_evidence _), _ -> assert false | Single (Activate_account _), KActivate -> return_unit | Single (Activate_account _), _ -> assert false | Single (Proposals _), KProposals -> return_unit diff --git a/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml b/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml index 32b1e228d5c3..97bdac0bc9b7 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml @@ -238,7 +238,7 @@ struct (failing_check_produce_result ~__LOC__ ~expected_error: - (Hist.Dal_proof_error + (Hist.Dal_page_proof_error "Wrong page content for the given page index and slot \ commitment (page id=(published_level: 1, slot_index: 0, \ page_index: 2)).")) @@ -260,7 +260,7 @@ struct (failing_check_produce_result ~__LOC__ ~expected_error: - (Hist.Dal_proof_error + (Hist.Dal_page_proof_error "Wrong page content for the given page index and slot \ commitment (page id=(published_level: 1, slot_index: 0, \ page_index: 0)).")) diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 45b518ad32bf..523fd85994e2 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -1602,6 +1602,10 @@ module Anonymous = struct in {vs with anonymous_state} + let check_dal_entrapment_evidence vi + (_operation : Kind.dal_entrapment_evidence operation) = + Dal.assert_incentives_enabled vi.ctxt |> Lwt.return + let check_drain_delegate info ~check_signature (operation : Kind.drain_delegate Operation.t) = let open Lwt_result_syntax in @@ -2504,6 +2508,8 @@ let check_operation ?(check_signature = true) info (type kind) Anonymous.check_double_attestation_evidence info operation | Single (Double_baking_evidence _) -> Anonymous.check_double_baking_evidence info operation + | Single (Dal_entrapment_evidence _) -> + Anonymous.check_dal_entrapment_evidence info operation | Single (Drain_delegate _) -> Anonymous.check_drain_delegate info ~check_signature operation | Single (Seed_nonce_revelation _) -> @@ -2572,6 +2578,9 @@ let check_operation_conflict (type kind) operation_conflict_state oph operation_conflict_state oph operation + | Single (Dal_entrapment_evidence _) -> + (* TODO: to be refined in the next commit *) + ok_unit | Single (Drain_delegate _) -> Anonymous.check_drain_delegate_conflict operation_conflict_state @@ -2624,6 +2633,9 @@ let add_valid_operation operation_conflict_state oph (type kind) operation_conflict_state oph operation + | Single (Dal_entrapment_evidence _) -> + (* TODO: to be refined in the next commit *) + operation_conflict_state | Single (Drain_delegate _) -> Anonymous.add_drain_delegate operation_conflict_state oph operation | Single (Seed_nonce_revelation _) -> @@ -2661,6 +2673,9 @@ let remove_operation operation_conflict_state (type kind) operation | Single (Double_baking_evidence _) -> Anonymous.remove_double_baking_evidence operation_conflict_state operation + | Single (Dal_entrapment_evidence _) -> + (* TODO: to be refined in the next commit *) + operation_conflict_state | Single (Drain_delegate _) -> Anonymous.remove_drain_delegate operation_conflict_state operation | Single (Seed_nonce_revelation _) -> @@ -2810,6 +2825,11 @@ let validate_operation ?(check_signature = true) add_double_baking_evidence operation_state oph operation in return {info; operation_state; block_state} + | Single (Dal_entrapment_evidence _) -> + let open Anonymous in + let* () = check_dal_entrapment_evidence info operation in + (* TODO: to be refined in the next commit *) + return {info; operation_state; block_state} | Single (Drain_delegate _) -> let open Anonymous in let* () = check_drain_delegate info ~check_signature operation in diff --git a/src/proto_alpha/lib_sc_rollup_node/sc_rollup_injector.ml b/src/proto_alpha/lib_sc_rollup_node/sc_rollup_injector.ml index 2cb82691c2dc..102b03789a4b 100644 --- a/src/proto_alpha/lib_sc_rollup_node/sc_rollup_injector.ml +++ b/src/proto_alpha/lib_sc_rollup_node/sc_rollup_injector.ml @@ -209,6 +209,7 @@ module Proto_client = struct | Double_attestation_evidence_result _ -> Successful | Double_preattestation_evidence_result _ -> Successful | Double_baking_evidence_result _ -> Successful + | Dal_entrapment_evidence_result _ -> Successful | Activate_account_result _ -> Successful | Proposals_result -> Successful | Ballot_result -> Successful -- GitLab From 7dbb8f933a78e746bae29757b933f5b1d3a14241 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Tue, 26 Nov 2024 15:39:06 +0100 Subject: [PATCH 4/5] Alpha/DAL: check conflicts for the DAL entrapment evidence op --- .../lib_protocol/operation_repr.ml | 43 ++++++-- .../lib_protocol/operation_repr.mli | 3 + src/proto_alpha/lib_protocol/validate.ml | 101 ++++++++++++++++-- src/proto_alpha/lib_protocol/validate.mli | 3 + .../lib_protocol/validate_errors.ml | 23 ++++ .../lib_protocol/validate_errors.mli | 1 + 6 files changed, 159 insertions(+), 15 deletions(-) diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index 9886d8332c8f..e56a47747c24 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -2100,6 +2100,8 @@ let consensus_infos_and_hash_from_block_header (bh : Block_header_repr.t) = in {round; bh_hash} +type dal_entrapment_info = {level : int32; number_of_attested_slots : int} + (** The weight of an operation. Given an operation, its [weight] carries on static information that @@ -2127,6 +2129,9 @@ let consensus_infos_and_hash_from_block_header (bh : Block_header_repr.t) = and [hash] of its first denounciated block_header. the [level] and [round] are wrapped in a {!double_baking_infos}. + The [weight] of a {!Dal_entrapment_evidence} is the level and the number of + DAL attested slots of the included attestation. + The [weight] of an {!Activate_account} depends on its public key hash. @@ -2150,8 +2155,7 @@ type _ weight = | Weight_double_attestation : round_infos -> anonymous_pass_type weight | Weight_double_baking : double_baking_infos -> anonymous_pass_type weight | Weight_dal_entrapment_evidence : - (* TODO: to be refined in the next commit *) - unit + dal_entrapment_info -> anonymous_pass_type weight | Weight_activate_account : Ed25519.Public_key_hash.t @@ -2267,8 +2271,21 @@ let weight_of : packed_operation -> operation_weight = consensus_infos_and_hash_from_block_header bh1 in W (Anonymous, Weight_double_baking double_baking_infos) - | Single (Dal_entrapment_evidence _) -> - W (Anonymous, Weight_dal_entrapment_evidence ()) + | Single (Dal_entrapment_evidence {attestation; _}) -> ( + match attestation.protocol_data.contents with + | Single (Attestation {consensus_content; dal_content}) -> + let info = + { + level = Raw_level_repr.to_int32 consensus_content.level; + number_of_attested_slots = + Option.fold + ~none:0 + ~some:(fun d -> + Dal_attestation_repr.number_of_attested_slots d.attestation) + dal_content; + } + in + W (Anonymous, Weight_dal_entrapment_evidence info)) | Single (Activate_account {id; _}) -> W (Anonymous, Weight_activate_account id) | Single (Drain_delegate {delegate; _}) -> @@ -2355,6 +2372,13 @@ let compare_attestation_infos ((infos1, slot1), n1) ((infos2, slot2), n2) +let compare_dal_entrapment_infos infos1 infos2 = + compare_pair_in_lexico_order + ~cmp_fst:Compare.Int32.compare + ~cmp_snd:Compare.Int.compare + (infos1.level, infos1.number_of_attested_slots) + (infos2.level, infos2.number_of_attested_slots) + (** {4 Comparison of valid operations of the same validation pass} *) (** {5 Comparison of valid consensus operations} *) @@ -2412,10 +2436,13 @@ let compare_vote_weight w1 w2 = is comparing their {!round_infos}, see {!compare_round_infos} for more details. - Comparing two {!Double_baking_evidence} is comparing as their + Comparing two {!Double_baking_evidence} is comparing as their {!double_baking_infos}, see {!compare_double_baking_infos} for more details. + Two {!Dal_entrapment_evidence} ops are compared by their level and the number of + slots they attest. + Two {!Seed_nonce_revelation} are compared by their [level]. Two {!Vdf_revelation} are compared by their [solution]. @@ -2460,12 +2487,14 @@ let compare_anonymous_weight w1 w2 = | Weight_vdf_revelation _ | Weight_activate_account _ | Weight_drain_delegate _ ) ) -> 1 - | Weight_dal_entrapment_evidence (), Weight_dal_entrapment_evidence () -> 0 + | Weight_dal_entrapment_evidence info1, Weight_dal_entrapment_evidence info2 + -> + compare_dal_entrapment_infos info1 info2 | ( ( Weight_seed_nonce_revelation _ | Weight_vdf_revelation _ | Weight_activate_account _ | Weight_drain_delegate _ ), Weight_dal_entrapment_evidence _ ) -> -1 - | ( Weight_dal_entrapment_evidence (), + | ( Weight_dal_entrapment_evidence _, ( Weight_seed_nonce_revelation _ | Weight_vdf_revelation _ | Weight_activate_account _ | Weight_drain_delegate _ ) ) -> 1 diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index b92ac2f13291..dd74dc626a55 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -622,6 +622,9 @@ val compare_by_passes : packed_operation -> packed_operation -> int in the case of equality, they are compared by the hashes of their first denounced block_header. + Two {!Dal_entrapment_evidence} ops are compared by their level and the number + of slots they attest. + Two {!Vdf_revelation} ops are compared by their [solution]. Two {!Seed_nonce_relevation} ops are compared by their [level]. diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 523fd85994e2..81090a6a935e 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -169,6 +169,22 @@ module Double_operation_evidence_map = struct elt_encoding)) end +module Dal_entrapment_map = struct + include Map.Make (struct + type t = Raw_level.t * Slot.t + + let compare (l1, s1) (l2, s2) = + Compare.or_else (Raw_level.compare l1 l2) @@ fun () -> Slot.compare s1 s2 + end) + + let encoding elt_encoding = + Data_encoding.conv + (fun map -> bindings map) + (fun l -> List.fold_left (fun m (k, v) -> add k v m) empty l) + Data_encoding.( + list (tup2 (tup2 Raw_level.encoding Slot.encoding) elt_encoding)) +end + (** State used and modified when validating anonymous operations. These fields are used to enforce that we do not validate the same operation multiple times. @@ -186,6 +202,7 @@ type anonymous_state = { double_baking_evidences_seen : Operation_hash.t Double_baking_evidence_map.t; double_attesting_evidences_seen : Operation_hash.t Double_operation_evidence_map.t; + dal_entrapments_seen : Operation_hash.t Dal_entrapment_map.t; seed_nonce_levels_seen : Operation_hash.t Raw_level.Map.t; vdf_solution_seen : Operation_hash.t option; } @@ -206,27 +223,31 @@ let anonymous_state_encoding = activation_pkhs_seen; double_baking_evidences_seen; double_attesting_evidences_seen; + dal_entrapments_seen; seed_nonce_levels_seen; vdf_solution_seen; } -> ( activation_pkhs_seen, double_baking_evidences_seen, double_attesting_evidences_seen, + dal_entrapments_seen, seed_nonce_levels_seen, vdf_solution_seen )) (fun ( activation_pkhs_seen, double_baking_evidences_seen, double_attesting_evidences_seen, + dal_entrapments_seen, seed_nonce_levels_seen, vdf_solution_seen ) -> { activation_pkhs_seen; double_baking_evidences_seen; double_attesting_evidences_seen; + dal_entrapments_seen; seed_nonce_levels_seen; vdf_solution_seen; }) - (obj5 + (obj6 (req "activation_pkhs_seen" (Ed25519.Public_key_hash.Map.encoding Operation_hash.encoding)) @@ -236,6 +257,9 @@ let anonymous_state_encoding = (req "double_attesting_evidences_seen" (Double_operation_evidence_map.encoding Operation_hash.encoding)) + (req + "dal_entrapments_seen" + (Dal_entrapment_map.encoding Operation_hash.encoding)) (req "seed_nonce_levels_seen" (raw_level_map_encoding Operation_hash.encoding)) @@ -246,6 +270,7 @@ let empty_anonymous_state = activation_pkhs_seen = Ed25519.Public_key_hash.Map.empty; double_baking_evidences_seen = Double_baking_evidence_map.empty; double_attesting_evidences_seen = Double_operation_evidence_map.empty; + dal_entrapments_seen = Dal_entrapment_map.empty; seed_nonce_levels_seen = Raw_level.Map.empty; vdf_solution_seen = None; } @@ -1606,6 +1631,55 @@ module Anonymous = struct (_operation : Kind.dal_entrapment_evidence operation) = Dal.assert_incentives_enabled vi.ctxt |> Lwt.return + let dal_entrapment_evidence_info + (operation : Kind.dal_entrapment_evidence operation) = + let (Single (Dal_entrapment_evidence {attestation; _})) = + operation.protocol_data.contents + in + let {level; slot; _} = + match attestation.protocol_data.contents with + | Single (Attestation {consensus_content; dal_content = _}) -> + consensus_content + in + (level, slot) + + let check_dal_entrapment_evidence_conflict vs oph + (operation : Kind.dal_entrapment_evidence operation) = + let level, tb_slot = dal_entrapment_evidence_info operation in + match + Dal_entrapment_map.find + (level, tb_slot) + vs.anonymous_state.dal_entrapments_seen + with + | None -> ok_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let wrap_dal_entrapment_evidence_conflict = function + | Ok () -> ok_unit + | Error conflict -> result_error (Conflicting_dal_entrapment conflict) + + let add_dal_entrapment_evidence vs oph + (operation : Kind.dal_entrapment_evidence operation) = + let level, tb_slot = dal_entrapment_evidence_info operation in + let dal_entrapments_seen = + Dal_entrapment_map.add + (level, tb_slot) + oph + vs.anonymous_state.dal_entrapments_seen + in + {vs with anonymous_state = {vs.anonymous_state with dal_entrapments_seen}} + + let remove_dal_entrapment_evidence vs + (operation : Kind.dal_entrapment_evidence operation) = + let level, tb_slot = dal_entrapment_evidence_info operation in + let dal_entrapments_seen = + Dal_entrapment_map.remove + (level, tb_slot) + vs.anonymous_state.dal_entrapments_seen + in + {vs with anonymous_state = {vs.anonymous_state with dal_entrapments_seen}} + let check_drain_delegate info ~check_signature (operation : Kind.drain_delegate Operation.t) = let open Lwt_result_syntax in @@ -2579,8 +2653,10 @@ let check_operation_conflict (type kind) operation_conflict_state oph oph operation | Single (Dal_entrapment_evidence _) -> - (* TODO: to be refined in the next commit *) - ok_unit + Anonymous.check_dal_entrapment_evidence_conflict + operation_conflict_state + oph + operation | Single (Drain_delegate _) -> Anonymous.check_drain_delegate_conflict operation_conflict_state @@ -2634,8 +2710,10 @@ let add_valid_operation operation_conflict_state oph (type kind) oph operation | Single (Dal_entrapment_evidence _) -> - (* TODO: to be refined in the next commit *) - operation_conflict_state + Anonymous.add_dal_entrapment_evidence + operation_conflict_state + oph + operation | Single (Drain_delegate _) -> Anonymous.add_drain_delegate operation_conflict_state oph operation | Single (Seed_nonce_revelation _) -> @@ -2674,8 +2752,9 @@ let remove_operation operation_conflict_state (type kind) | Single (Double_baking_evidence _) -> Anonymous.remove_double_baking_evidence operation_conflict_state operation | Single (Dal_entrapment_evidence _) -> - (* TODO: to be refined in the next commit *) - operation_conflict_state + Anonymous.remove_dal_entrapment_evidence + operation_conflict_state + operation | Single (Drain_delegate _) -> Anonymous.remove_drain_delegate operation_conflict_state operation | Single (Seed_nonce_revelation _) -> @@ -2828,7 +2907,13 @@ let validate_operation ?(check_signature = true) | Single (Dal_entrapment_evidence _) -> let open Anonymous in let* () = check_dal_entrapment_evidence info operation in - (* TODO: to be refined in the next commit *) + let*? () = + check_dal_entrapment_evidence_conflict operation_state oph operation + |> wrap_dal_entrapment_evidence_conflict + in + let operation_state = + add_dal_entrapment_evidence operation_state oph operation + in return {info; operation_state; block_state} | Single (Drain_delegate _) -> let open Anonymous in diff --git a/src/proto_alpha/lib_protocol/validate.mli b/src/proto_alpha/lib_protocol/validate.mli index 1afd0828ca0c..6ddac615779d 100644 --- a/src/proto_alpha/lib_protocol/validate.mli +++ b/src/proto_alpha/lib_protocol/validate.mli @@ -305,6 +305,9 @@ val check_operation : (** Check that the operation does not conflict with other operations already validated and recorded in the {!operation_conflict_state}. + Two {!Dal_entrapment_evidence} are in conflict if their consensus + attestations have the same level and the same slot. + This function is intended for {!Mempool_validation} exclusively. *) val check_operation_conflict : operation_conflict_state -> diff --git a/src/proto_alpha/lib_protocol/validate_errors.ml b/src/proto_alpha/lib_protocol/validate_errors.ml index 47514dfb2c08..87299d7dadd7 100644 --- a/src/proto_alpha/lib_protocol/validate_errors.ml +++ b/src/proto_alpha/lib_protocol/validate_errors.ml @@ -893,6 +893,29 @@ module Anonymous = struct (fun (kind, level, last_cycle) -> Outdated_denunciation {kind; level; last_cycle}) + type error += Conflicting_dal_entrapment of operation_conflict + + let () = + register_error_kind + `Branch + ~id:"validate.operation.conflicting_dal_entrapment" + ~title:"Conflicting DAL entrapment in the current validation state)." + ~description: + "A DAL entrapment evidence for the same level and a larger DAL \ + attestation has already been validated for the current validation \ + state." + ~pp:(fun ppf (Operation_conflict {existing; _}) -> + Format.fprintf + ppf + "This DAL entrapment evidence is conflicting with an existing \ + entrapment evidence %a" + Operation_hash.pp + existing) + Data_encoding.(obj1 (req "conflict" operation_conflict_encoding)) + (function + | Conflicting_dal_entrapment conflict -> Some conflict | _ -> None) + (fun conflict -> Conflicting_dal_entrapment conflict) + type error += Conflicting_nonce_revelation of operation_conflict let () = diff --git a/src/proto_alpha/lib_protocol/validate_errors.mli b/src/proto_alpha/lib_protocol/validate_errors.mli index b3f7956f56ea..ac2d36e01ab3 100644 --- a/src/proto_alpha/lib_protocol/validate_errors.mli +++ b/src/proto_alpha/lib_protocol/validate_errors.mli @@ -155,6 +155,7 @@ module Anonymous : sig level : Raw_level.t; last_cycle : Cycle.t; } + | Conflicting_dal_entrapment of operation_conflict | Conflicting_nonce_revelation of operation_conflict | Conflicting_vdf_revelation of operation_conflict | Drain_delegate_on_unregistered_delegate of Signature.Public_key_hash.t -- GitLab From 55dcd7c6ddab0ae2b3e4e38dab928d72f8b6f2bb Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Mon, 2 Dec 2024 14:21:02 +0100 Subject: [PATCH 5/5] CHANGES: updates --- CHANGES.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index a3e3bd066a52..5edf20d2fba7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -186,5 +186,12 @@ DAL node - **Breaking change** The baker daemon ``--dal-node-timeout-percentage`` argument has been removed. (MR :gl:`!15554`) +Protocol +~~~~~~~~ + +- A new antonymous operation "DAL entrapment evidence" was added. This operation + is not valid when the feature flag for DAL incentives is turned off. (MR + :gl:`!15677`) + Miscellaneous ------------- -- GitLab