From ec7c5d9871709db5f1dc967b8dc2b5a0a242d54c Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Tue, 21 Feb 2023 17:57:44 +0100 Subject: [PATCH 1/7] Proto: finalize_validate_block_header only takes fitness locked_round instead of the whole fitness as argument. This will allow us to remove some information from the modes in the next commit. --- .../lib_protocol/alpha_context.mli | 2 +- .../lib_protocol/block_header_repr.ml | 5 ++-- .../lib_protocol/block_header_repr.mli | 2 +- src/proto_alpha/lib_protocol/fitness_repr.ml | 12 ++-------- src/proto_alpha/lib_protocol/fitness_repr.mli | 5 +++- src/proto_alpha/lib_protocol/validate.ml | 24 +++++-------------- 6 files changed, 17 insertions(+), 33 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index ec95f9c2752e..94c182405d1a 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -4387,7 +4387,7 @@ module Block_header : sig val finalize_validate_block_header : block_header_contents:contents -> round:Round.t -> - fitness:Fitness.t -> + fitness_locked_round:Round.t option -> checkable_payload_hash:checkable_payload_hash -> locked_round_evidence:locked_round_evidence option -> consensus_threshold:int -> diff --git a/src/proto_alpha/lib_protocol/block_header_repr.ml b/src/proto_alpha/lib_protocol/block_header_repr.ml index 41b5988a7f9b..db1065225517 100644 --- a/src/proto_alpha/lib_protocol/block_header_repr.ml +++ b/src/proto_alpha/lib_protocol/block_header_repr.ml @@ -470,7 +470,7 @@ let finalize_validate_block_header ~(block_header_contents : contents) ~(round : Round_repr.t) ~(* We have to check the round because in the construction case it was deduced from the time *) - (fitness : Fitness_repr.t) + (fitness_locked_round : Round_repr.t option) ~(checkable_payload_hash : checkable_payload_hash) ~(locked_round_evidence : locked_round_evidence option) ~(consensus_threshold : int) = @@ -502,4 +502,5 @@ let finalize_validate_block_header ~(block_header_contents : contents) (Insufficient_locked_round_evidence {voting_power = preendorsement_count; consensus_threshold}) >>? fun () -> ok (Some preendorsement_round)) - >>? fun locked_round -> Fitness_repr.check_locked_round fitness ~locked_round + >>? fun locked_round -> + Fitness_repr.check_locked_round ~fitness_locked_round ~locked_round diff --git a/src/proto_alpha/lib_protocol/block_header_repr.mli b/src/proto_alpha/lib_protocol/block_header_repr.mli index a84761403288..7af93f3ab813 100644 --- a/src/proto_alpha/lib_protocol/block_header_repr.mli +++ b/src/proto_alpha/lib_protocol/block_header_repr.mli @@ -127,7 +127,7 @@ type checkable_payload_hash = val finalize_validate_block_header : block_header_contents:contents -> round:Round_repr.t -> - fitness:Fitness_repr.t -> + fitness_locked_round:Round_repr.t option -> checkable_payload_hash:checkable_payload_hash -> locked_round_evidence:locked_round_evidence option -> consensus_threshold:int -> diff --git a/src/proto_alpha/lib_protocol/fitness_repr.ml b/src/proto_alpha/lib_protocol/fitness_repr.ml index 8abc162cf542..c802021f371b 100644 --- a/src/proto_alpha/lib_protocol/fitness_repr.ml +++ b/src/proto_alpha/lib_protocol/fitness_repr.ml @@ -244,17 +244,9 @@ let check_except_locked_round fitness ~level ~predecessor_round = in error_unless correct Wrong_fitness -let check_locked_round fitness ~locked_round = - let { - level = _; - locked_round = expected_locked_round; - predecessor_round = _; - round = _; - } = - fitness - in +let check_locked_round ~fitness_locked_round ~locked_round = let correct = - match (locked_round, expected_locked_round) with + match (locked_round, fitness_locked_round) with | None, None -> true | Some _, None | None, Some _ -> false | Some v, Some v' -> Round_repr.(v = v') diff --git a/src/proto_alpha/lib_protocol/fitness_repr.mli b/src/proto_alpha/lib_protocol/fitness_repr.mli index 7a3ebaa8afe4..00aff9accfe9 100644 --- a/src/proto_alpha/lib_protocol/fitness_repr.mli +++ b/src/proto_alpha/lib_protocol/fitness_repr.mli @@ -77,7 +77,10 @@ val check_except_locked_round : (** Validate the locked_round component of the fitness, which could not be validated during begin_application. *) -val check_locked_round : t -> locked_round:Round_repr.t option -> unit tzresult +val check_locked_round : + fitness_locked_round:Round_repr.t option -> + locked_round:Round_repr.t option -> + unit tzresult val level : t -> Raw_level_repr.t diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 48e6af5a0a07..a3890a2173e2 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -3221,7 +3221,8 @@ let check_endorsement_power vi bs = (Validate_errors.Block.Not_enough_endorsements {required; provided}) let finalize_validate_block_header vi vs checkable_payload_hash - (block_header_contents : Block_header.contents) round fitness = + (block_header_contents : Block_header.contents) round ~fitness_locked_round + = let locked_round_evidence = Option.map (fun (preendorsement_round, preendorsement_count) -> @@ -3231,7 +3232,7 @@ let finalize_validate_block_header vi vs checkable_payload_hash Block_header.finalize_validate_block_header ~block_header_contents ~round - ~fitness + ~fitness_locked_round ~checkable_payload_hash ~locked_round_evidence ~consensus_threshold:(Constants.consensus_threshold vi.ctxt) @@ -3264,7 +3265,7 @@ let finalize_block {info; block_state; _} = (Block_header.Expected_payload_hash block_payload_hash) block_data_contents round - fitness + ~fitness_locked_round:(Fitness.locked_round fitness) in return_unit | Partial_validation _ -> @@ -3275,8 +3276,7 @@ let finalize_block {info; block_state; _} = else ok_unit in return_unit - | Construction - {predecessor_round; predecessor_hash; round; block_data_contents; _} -> + | Construction {predecessor_hash; round; block_data_contents; _} -> let block_payload_hash = compute_payload_hash block_state block_data_contents ~predecessor_hash in @@ -3300,18 +3300,6 @@ let finalize_block {info; block_state; _} = check_endorsement_power info block_state else ok_unit in - let* fitness = - let locked_round = - match locked_round_evidence with - | None -> None - | Some (preendorsement_round, _power) -> Some preendorsement_round - in - let level = (Level.current info.ctxt).level in - let*? fitness = - Fitness.create ~level ~round ~predecessor_round ~locked_round - in - return fitness - in let*? () = finalize_validate_block_header info @@ -3319,7 +3307,7 @@ let finalize_block {info; block_state; _} = checkable_payload_hash block_data_contents round - fitness + ~fitness_locked_round:(Option.map fst locked_round_evidence) in return_unit | Mempool -> -- GitLab From 1204dab5d7f8fd26edb7a383b37caa73239d5ead Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 22 Feb 2023 14:32:28 +0100 Subject: [PATCH 2/7] Proto/validate: update info and mode types with information that will be useful to handle consensus operation checks directly, without relying on all_expected_consensus_features. --- src/proto_alpha/lib_protocol/validate.ml | 203 ++++++++++++++--------- 1 file changed, 123 insertions(+), 80 deletions(-) diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index a3890a2173e2..665b68debc51 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -94,13 +94,18 @@ type all_expected_consensus_features = { } type consensus_info = { + predecessor_level : Raw_level.t; + predecessor_round : Round.t; all_expected_features : all_expected_consensus_features; preendorsement_slot_map : (Consensus_key.pk * int) Slot.Map.t; endorsement_slot_map : (Consensus_key.pk * int) Slot.Map.t; } -let init_consensus_info ctxt all_expected_features = +let init_consensus_info ctxt ~predecessor_level ~predecessor_round + all_expected_features = { + predecessor_level; + predecessor_round; all_expected_features; preendorsement_slot_map = Consensus.allowed_preendorsements ctxt; endorsement_slot_map = Consensus.allowed_endorsements ctxt; @@ -125,6 +130,10 @@ module Consensus_content_map = Map.Make (struct end) type consensus_state = { + (* The [predecessor_level] is needed here, despite being also in + {!consensus_info}, because it allows to identify grandparent + endorsements in [check_endorsement_conflict] where we only have + access to the [consensus_state]. *) predecessor_level : Raw_level.t; preendorsements_seen : Operation_hash.t Slot.Map.t; endorsements_seen : Operation_hash.t Slot.Map.t; @@ -378,48 +387,60 @@ let manager_state_encoding = let empty_manager_state = {managers_seen = Signature.Public_key_hash.Map.empty} -(** Mode-dependent information needed in final checks. *) -type block_finalization_info = { - fitness : Fitness.t; +(** Information needed to validate consensus operations and/or to + finalize the block in both modes that handle a preexisting block: + [Application] and [Partial_validation]. *) +type block_info = { + round : Round.t; + locked_round : Round.t option; + predecessor_hash : Block_hash.t; block_producer : Consensus_key.pk; payload_producer : Consensus_key.pk; - predecessor_hash : Block_hash.t; - block_data_contents : Block_header.contents; + header_contents : Block_header.contents; } -(** Circumstances in which operations are validated, and corresponding - information. - - - [Application] is used for the validation of a preexisting block, - often in preparation for its future application. - - - [Partial_validation] is used to quickly but partially validate a - preexisting block, e.g. to quickly decide whether an alternate - branch seems viable. In this mode, the initial {!type:context} may - come from an ancestor block instead of the predecessor block. Only - consensus operations are validated in this mode. +(** Information needed to validate consensus operations and/or to + finalize the block in [Construction] mode. *) +type construction_info = { + round : Round.t; + predecessor_hash : Block_hash.t; + block_producer : Consensus_key.pk; + payload_producer : Consensus_key.pk; + header_contents : Block_header.contents; +} - - [Construction] is used for the construction of a new block. +(** Information needed to validate grandparent endorsements in + [Mempool] mode. *) +type grandparent = { + round : Round.t; + hash : Block_hash.t; + payload_hash : Block_payload_hash.t; +} - - [Mempool] is used by the {!module:Mempool} and by the - [Partial_construction] mode in {!module:Main}, which may itself be - used by RPCs or by another mempool implementation. (The [Mempool] - mode is also used by the plugin.) +(** Circumstances in which operations are validated, and corresponding + specific information. If you add a new mode, please make sure that it has a way to bound - the size of the map {!recfield:manager_state.managers_seen}. *) + the size of the maps in the {!operation_conflict_state}. *) type mode = - | Application of block_finalization_info - | Partial_validation of block_finalization_info - | Construction of { - predecessor_round : Round.t; - predecessor_hash : Block_hash.t; - round : Round.t; - block_data_contents : Block_header.contents; - block_producer : Consensus_key.pk; - payload_producer : Consensus_key.pk; - } - | Mempool + | Application of block_info + (** [Application] is used for the validation of a preexisting block, + often in preparation for its future application. *) + | Partial_validation of block_info + (** [Partial_validation] is used to quickly but partially validate a + preexisting block, e.g. to quickly decide whether an alternate + branch seems viable. In this mode, the initial {!type:context} may + come from an ancestor block instead of the predecessor block. Only + consensus operations are validated in this mode. *) + | Construction of construction_info + (** Used for the construction of a new block. *) + | Mempool of grandparent option + (** Used by the mempool ({!module:Mempool_validation}) and by the + [Partial_construction] mode in {!module:Main}, which may itself be + used by RPCs or by another mempool implementation. + + If the option is [None], it means that there cannot be any + grandparent endorsements. *) (** {2 Definition and initialization of [info] and [state]} *) @@ -470,14 +491,19 @@ type validation_state = { let ok_unit = Result_syntax.return_unit -let init_info ctxt mode chain_id all_expected_consensus_characteristics = +let init_info ctxt mode chain_id ~predecessor_level ~predecessor_round + all_expected_consensus_characteristics = { ctxt; mode; chain_id; current_level = Level.current ctxt; consensus_info = - init_consensus_info ctxt all_expected_consensus_characteristics; + init_consensus_info + ctxt + ~predecessor_level + ~predecessor_round + all_expected_consensus_characteristics; manager_info = init_manager_info ctxt; } @@ -655,7 +681,7 @@ module Consensus = struct Consensus_operation_for_old_round {kind; expected; provided} else Consensus_operation_for_future_round {kind; expected; provided}) - let check_round_equal kind expected_features + let check_round_equal kind (expected_features : expected_features) (consensus_content : consensus_content) = match expected_features.round with | Some expected -> check_round kind expected consensus_content @@ -668,7 +694,7 @@ module Consensus = struct (Block_hash.equal expected provided) (Wrong_consensus_operation_branch {kind; expected; provided}) - let check_payload_hash_equal kind expected_features + let check_payload_hash_equal kind (expected_features : expected_features) (consensus_content : consensus_content) = let expected = expected_features.payload_hash in let provided = consensus_content.block_payload_hash in @@ -792,7 +818,7 @@ module Consensus = struct (consensus_content : consensus_content) voting_power = let locked_round_evidence = match mode with - | Mempool -> None + | Mempool _ -> (* The block_state is not relevant in this mode. *) None | Application _ | Partial_validation _ | Construction _ -> ( match block_state.locked_round_evidence with | None -> Some (consensus_content.round, voting_power) @@ -2336,7 +2362,7 @@ module Manager = struct let may_trace_gas_limit_too_high info = match info.mode with | Application _ | Partial_validation _ | Construction _ -> fun x -> x - | Mempool -> + | Mempool _ -> (* [Gas.check_limit] will only raise a "temporary" error, however when {!validate_operation} is called on a batch in isolation @@ -2553,7 +2579,7 @@ module Manager = struct Gas.Arith.(sub block_state.remaining_block_gas operation_gas_used) in {block_state with remaining_block_gas} - | Mempool -> block_state + | Mempool _ -> block_state let remove_manager_operation (type kind) vs (operation : kind Kind.manager operation) = @@ -2590,8 +2616,16 @@ module Manager = struct end let init_validation_state ctxt mode chain_id all_expected_consensus_features - ~predecessor_level = - let info = init_info ctxt mode chain_id all_expected_consensus_features in + ~predecessor_level ~predecessor_round = + let info = + init_info + ctxt + mode + chain_id + ~predecessor_level + ~predecessor_round + all_expected_consensus_features + in let operation_state = init_operation_conflict_state ~predecessor_level in let block_state = init_block_state info in {info; operation_state; block_state} @@ -2638,18 +2672,18 @@ let begin_any_application ctxt chain_id ~predecessor_level in let payload_hash = block_header.protocol_data.contents.payload_hash in let predecessor_hash = block_header.shell.predecessor in - let block_finalization_info = + let block_info = { - fitness; + round; + locked_round = Fitness.locked_round fitness; + predecessor_hash; block_producer; payload_producer; - predecessor_hash; - block_data_contents = block_header.protocol_data.contents; + header_contents = block_header.protocol_data.contents; } in let mode = - if is_partial then Partial_validation block_finalization_info - else Application block_finalization_info + if is_partial then Partial_validation block_info else Application block_info in let all_expected_consensus_features = Consensus.expected_features_for_application @@ -2660,14 +2694,16 @@ let begin_any_application ctxt chain_id ~predecessor_level ~predecessor_round ~predecessor_hash in - let predecessor_level = predecessor_level.level in - return - (init_validation_state - ctxt - mode - chain_id - all_expected_consensus_features - ~predecessor_level) + let validation_state = + init_validation_state + ctxt + mode + chain_id + all_expected_consensus_features + ~predecessor_level:predecessor_level.level + ~predecessor_round + in + return validation_state let begin_partial_validation ctxt chain_id ~predecessor_level ~predecessor_timestamp block_header fitness = @@ -2727,22 +2763,21 @@ let begin_full_construction ctxt chain_id ~predecessor_level ~predecessor_round ~predecessor_round ~predecessor_hash in - let predecessor_level = predecessor_level.level in let validation_state = init_validation_state ctxt (Construction { - predecessor_round; - predecessor_hash; round; - block_data_contents = header_contents; + predecessor_hash; block_producer; payload_producer; + header_contents; }) chain_id all_expected_consensus_features - ~predecessor_level + ~predecessor_level:predecessor_level.level + ~predecessor_round in return validation_state @@ -2755,14 +2790,20 @@ let begin_partial_construction ctxt chain_id ~predecessor_level ~predecessor_round ~grandparent_round in - let predecessor_level = predecessor_level.level in + let grandparent = + Option.map + (fun (hash, payload_hash) -> + {round = grandparent_round; hash; payload_hash}) + (Alpha_context.Consensus.grand_parent_branch ctxt) + in let validation_state = init_validation_state ctxt - Mempool + (Mempool grandparent) chain_id all_expected_consensus_features - ~predecessor_level + ~predecessor_level:predecessor_level.level + ~predecessor_round in validation_state @@ -2783,10 +2824,13 @@ let begin_no_predecessor_info ctxt chain_id = in init_validation_state ctxt - Mempool + (Mempool None) chain_id all_expected_consensus_features ~predecessor_level + (* Fake predecessor_round because all consensus + operations should be rejected anyway. *) + ~predecessor_round:Round.zero let check_operation ?(check_signature = true) info (type kind) (operation : kind operation) : unit tzresult Lwt.t = @@ -3007,7 +3051,7 @@ let remove_operation operation_conflict_state (type kind) let check_validation_pass_consistency vi vs validation_pass = let open Lwt_result_syntax in match vi.mode with - | Mempool | Construction _ -> return vs + | Mempool _ | Construction _ -> return vs | Application _ | Partial_validation _ -> ( match (vs.last_op_validation_pass, validation_pass) with | None, validation_pass -> @@ -3052,10 +3096,10 @@ let validate_operation ?(check_signature = true) match (info.mode, validation_pass_opt) with | Partial_validation _, Some n when Compare.Int.(n <> Operation_repr.consensus_pass) -> - (* Do not validate non-consensus operation in [Partial_validation] mode *) + (* Do not validate non-consensus operations in + [Partial_validation] mode. *) return {info; operation_state; block_state} - | Partial_validation _, _ | Mempool, _ | Construction _, _ | Application _, _ - -> ( + | (Application _ | Partial_validation _ | Construction _ | Mempool _), _ -> ( match operation.protocol_data.contents with | Single (Preendorsement _) -> Consensus.validate_preendorsement @@ -3247,7 +3291,7 @@ let compute_payload_hash block_state let finalize_block {info; block_state; _} = let open Lwt_result_syntax in match info.mode with - | Application {fitness; predecessor_hash; block_data_contents; _} -> + | Application {round; locked_round; predecessor_hash; header_contents; _} -> let* are_endorsements_required = are_endorsements_required info in let*? () = if are_endorsements_required then @@ -3255,17 +3299,16 @@ let finalize_block {info; block_state; _} = else ok_unit in let block_payload_hash = - compute_payload_hash block_state block_data_contents ~predecessor_hash + compute_payload_hash block_state header_contents ~predecessor_hash in - let round = Fitness.round fitness in let*? () = finalize_validate_block_header info block_state (Block_header.Expected_payload_hash block_payload_hash) - block_data_contents + header_contents round - ~fitness_locked_round:(Fitness.locked_round fitness) + ~fitness_locked_round:locked_round in return_unit | Partial_validation _ -> @@ -3276,9 +3319,9 @@ let finalize_block {info; block_state; _} = else ok_unit in return_unit - | Construction {predecessor_hash; round; block_data_contents; _} -> + | Construction {round; predecessor_hash; header_contents; _} -> let block_payload_hash = - compute_payload_hash block_state block_data_contents ~predecessor_hash + compute_payload_hash block_state header_contents ~predecessor_hash in let locked_round_evidence = block_state.locked_round_evidence in let checkable_payload_hash = @@ -3305,11 +3348,11 @@ let finalize_block {info; block_state; _} = info block_state checkable_payload_hash - block_data_contents + header_contents round ~fitness_locked_round:(Option.map fst locked_round_evidence) in return_unit - | Mempool -> - (* Nothing to do for the mempool mode*) + | Mempool _ -> + (* There is no block to finalize in mempool mode. *) return_unit -- GitLab From 7d8b4709aa284479df3560a8cbafa45eab6bcf5c Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Thu, 23 Feb 2023 11:41:02 +0100 Subject: [PATCH 3/7] Proto/validate: make consensus_info an option in case there is missing predecessor information and all consensus ops should be rejected --- src/proto_alpha/lib_protocol/validate.ml | 91 ++++++++++++++---------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 665b68debc51..ede3f6670a30 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -101,8 +101,8 @@ type consensus_info = { endorsement_slot_map : (Consensus_key.pk * int) Slot.Map.t; } -let init_consensus_info ctxt ~predecessor_level ~predecessor_round - all_expected_features = +let init_consensus_info ctxt all_expected_features + (predecessor_level, predecessor_round) = { predecessor_level; predecessor_round; @@ -449,7 +449,11 @@ type info = { mode : mode; chain_id : Chain_id.t; (** Needed for signature checks. *) current_level : Level.t; - consensus_info : consensus_info; + consensus_info : consensus_info option; + (** Needed to validate consensus operations. This can be [None] during + some RPC calls when some predecessor information is unavailable, + in which case the validation of all consensus operations will + systematically fail. *) manager_info : manager_info; } @@ -491,19 +495,19 @@ type validation_state = { let ok_unit = Result_syntax.return_unit -let init_info ctxt mode chain_id ~predecessor_level ~predecessor_round +let init_info ctxt mode chain_id ~predecessor_level_and_round all_expected_consensus_characteristics = + let consensus_info = + Option.map + (init_consensus_info ctxt all_expected_consensus_characteristics) + predecessor_level_and_round + in { ctxt; mode; chain_id; current_level = Level.current ctxt; - consensus_info = - init_consensus_info - ctxt - ~predecessor_level - ~predecessor_round - all_expected_consensus_characteristics; + consensus_info; manager_info = init_manager_info ctxt; } @@ -745,12 +749,17 @@ module Consensus = struct let check_preendorsement vi ~check_signature (operation : Kind.preendorsement operation) = let open Lwt_result_syntax in + let*? consensus_info = + Option.value_e + ~error:(trace_of_error Consensus_operation_not_allowed) + vi.consensus_info + in let (Single (Preendorsement consensus_content)) = operation.protocol_data.contents in let kind = Preendorsement in let*? expected_features, block_round = - get_expected_preendorsements_features vi.consensus_info consensus_content + get_expected_preendorsements_features consensus_info consensus_content in let*? () = check_round_not_too_high ~block_round ~provided:consensus_content.round @@ -764,7 +773,7 @@ module Consensus = struct in let*? consensus_key, voting_power = get_delegate_details - vi.consensus_info.preendorsement_slot_map + consensus_info.preendorsement_slot_map kind consensus_content in @@ -929,7 +938,7 @@ module Consensus = struct (** Validate an endorsement pointing to the predecessor, aka a "normal" endorsement. Only this kind of endorsement may be found during block validation or construction. *) - let check_normal_endorsement vi ~check_signature + let check_normal_endorsement vi consensus_info ~check_signature (operation : Kind.endorsement operation) = let open Lwt_result_syntax in let (Single (Endorsement consensus_content)) = @@ -937,7 +946,7 @@ module Consensus = struct in let kind = Endorsement in let*? expected_features = - get_expected_endorsements_features vi.consensus_info consensus_content + get_expected_endorsements_features consensus_info consensus_content in let*? () = check_consensus_features @@ -948,7 +957,7 @@ module Consensus = struct in let*? consensus_key, voting_power = get_delegate_details - vi.consensus_info.endorsement_slot_map + consensus_info.endorsement_slot_map kind consensus_content in @@ -1004,11 +1013,16 @@ module Consensus = struct let check_endorsement vi ~check_signature (operation : Kind.endorsement operation) = let open Lwt_result_syntax in + let*? consensus_info = + Option.value_e + ~error:(trace_of_error Consensus_operation_not_allowed) + vi.consensus_info + in let (Single (Endorsement consensus_content)) = operation.protocol_data.contents in match - vi.consensus_info.all_expected_features + consensus_info.all_expected_features .expected_grandparent_endorsement_for_partial_construction with | Some expected_grandparent_endorsement @@ -1026,7 +1040,7 @@ module Consensus = struct return Grandparent_endorsement | _ -> let* voting_power = - check_normal_endorsement vi ~check_signature operation + check_normal_endorsement vi consensus_info ~check_signature operation in return (Normal_endorsement voting_power) @@ -1143,8 +1157,13 @@ module Consensus = struct let check_construction_preendorsement_round_consistency vi block_state kind (consensus_content : consensus_content) = let open Result_syntax in + let* consensus_info = + Option.value_e + ~error:(trace_of_error Consensus_operation_not_allowed) + vi.consensus_info + in let* expected_features, _block_round = - get_expected_preendorsements_features vi.consensus_info consensus_content + get_expected_preendorsements_features consensus_info consensus_content in match expected_features.round with | Some _ -> @@ -2616,16 +2635,23 @@ module Manager = struct end let init_validation_state ctxt mode chain_id all_expected_consensus_features - ~predecessor_level ~predecessor_round = + ~predecessor_level_and_round = let info = init_info ctxt mode chain_id - ~predecessor_level - ~predecessor_round + ~predecessor_level_and_round all_expected_consensus_features in + let predecessor_level = + match predecessor_level_and_round with + | Some (predecessor_level, _) -> predecessor_level + | None -> + (* Fake predecessor level that will not be used since the + validation of all consensus operations will fail. *) + info.current_level.level + in let operation_state = init_operation_conflict_state ~predecessor_level in let block_state = init_block_state info in {info; operation_state; block_state} @@ -2700,8 +2726,8 @@ let begin_any_application ctxt chain_id ~predecessor_level mode chain_id all_expected_consensus_features - ~predecessor_level:predecessor_level.level - ~predecessor_round + ~predecessor_level_and_round: + (Some (predecessor_level.level, predecessor_round)) in return validation_state @@ -2776,8 +2802,8 @@ let begin_full_construction ctxt chain_id ~predecessor_level ~predecessor_round }) chain_id all_expected_consensus_features - ~predecessor_level:predecessor_level.level - ~predecessor_round + ~predecessor_level_and_round: + (Some (predecessor_level.level, predecessor_round)) in return validation_state @@ -2802,8 +2828,8 @@ let begin_partial_construction ctxt chain_id ~predecessor_level (Mempool grandparent) chain_id all_expected_consensus_features - ~predecessor_level:predecessor_level.level - ~predecessor_round + ~predecessor_level_and_round: + (Some (predecessor_level.level, predecessor_round)) in validation_state @@ -2816,21 +2842,12 @@ let begin_no_predecessor_info ctxt chain_id = expected_grandparent_endorsement_for_partial_construction = None; } in - let current_level = Level.current ctxt in - let predecessor_level = - match Raw_level.pred current_level.level with - | None -> current_level.level - | Some level -> level - in init_validation_state ctxt (Mempool None) chain_id all_expected_consensus_features - ~predecessor_level - (* Fake predecessor_round because all consensus - operations should be rejected anyway. *) - ~predecessor_round:Round.zero + ~predecessor_level_and_round:None let check_operation ?(check_signature = true) info (type kind) (operation : kind operation) : unit tzresult Lwt.t = -- GitLab From 13ff114f8d18f25dc54c11a48e940f52c23f0a63 Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 22 Feb 2023 14:52:29 +0100 Subject: [PATCH 4/7] Proto/validate: update preendorsement checks --- src/proto_alpha/lib_protocol/validate.ml | 206 +++++++++++++++-------- 1 file changed, 133 insertions(+), 73 deletions(-) diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index ede3f6670a30..cb71433c1c2f 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -714,38 +714,104 @@ module Consensus = struct let* () = check_branch_equal kind expected operation in check_payload_hash_equal kind expected consensus_content - let get_expected_preendorsements_features consensus_info consensus_content = - match consensus_info.all_expected_features.expected_preendorsement with - | Expected_preendorsement {expected_features; block_round} -> - ok (expected_features, block_round) - | No_locked_round_for_block_validation_preendorsement - | Fresh_proposal_for_construction_preendorsement -> - error Unexpected_preendorsement_in_block - | No_expected_branch_for_partial_construction_preendorsement - {expected_level} -> - error - (Consensus_operation_for_future_level - { - kind = Preendorsement; - expected = expected_level; - provided = consensus_content.Alpha_context.level; - }) - | No_predecessor_info_cannot_validate_preendorsement -> - error Consensus_operation_not_allowed - - let check_round_not_too_high ~block_round ~provided = - match block_round with - | None -> ok_unit - | Some block_round -> - error_unless - Round.(provided < block_round) - (Preendorsement_round_too_high {block_round; provided}) - let get_delegate_details slot_map kind consensus_content = Result.of_option (Slot.Map.find consensus_content.slot slot_map) ~error:(trace_of_error (Wrong_slot_used_for_consensus_operation {kind})) + (** When validating a block (ie. in [Application], + [Partial_validation], and [Construction] modes), any + preendorsements must point to a round that is strictly before the + block's round. *) + let check_round_before_block ~block_round provided = + error_unless + Round.(provided < block_round) + (Preendorsement_round_too_high {block_round; provided}) + + let check_level kind expected provided = + (* We use [if] instead of [error_unless] to avoid computing the + error when it is not needed. *) + if Raw_level.equal expected provided then Result.return_unit + else if Raw_level.(expected > provided) then + error (Consensus_operation_for_old_level {kind; expected; provided}) + else error (Consensus_operation_for_future_level {kind; expected; provided}) + + let check_round kind expected provided = + (* We use [if] instead of [error_unless] to avoid computing the + error when it is not needed. *) + if Round.equal expected provided then Result.return_unit + else if Round.(expected > provided) then + error (Consensus_operation_for_old_round {kind; expected; provided}) + else error (Consensus_operation_for_future_round {kind; expected; provided}) + + let check_branch kind expected provided = + error_unless + (Block_hash.equal expected provided) + (Wrong_consensus_operation_branch {kind; expected; provided}) + + let check_payload_hash kind expected provided = + error_unless + (Block_payload_hash.equal expected provided) + (Wrong_payload_hash_for_consensus_operation {kind; expected; provided}) + + (** Check the preendorsement features for both [Application] and + [Partial_validation] modes. *) + let check_preendorsement_content_preexisting_block vi block_info branch + {level; round; block_payload_hash; _} = + let open Result_syntax in + let* locked_round = + match block_info.locked_round with + | Some locked_round -> return locked_round + | None -> + (* A preexisting block whose fitness has no locked round + should contain no preendorsements. *) + error Unexpected_preendorsement_in_block + in + let kind = Preendorsement in + let* () = check_round_before_block ~block_round:block_info.round round in + let* () = check_level kind vi.current_level.level level in + let* () = check_round kind locked_round round in + let* () = check_branch kind block_info.predecessor_hash branch in + let expected_payload_hash = block_info.header_contents.payload_hash in + check_payload_hash kind expected_payload_hash block_payload_hash + + let check_preendorsement_content_construction vi cons_info branch + {level; round; block_payload_hash; _} = + let open Result_syntax in + let expected_payload_hash = cons_info.header_contents.payload_hash in + let* () = + (* When the proposal is fresh, a fake [payload_hash] of [zero] + has been provided. In this case, the block should not contain + any preendorsements. *) + error_when + Block_payload_hash.(expected_payload_hash = zero) + Unexpected_preendorsement_in_block + in + let kind = Preendorsement in + let* () = check_round_before_block ~block_round:cons_info.round round in + let* () = check_level kind vi.current_level.level level in + (* We cannot check the exact round here in construction mode, because + there is no preexisting fitness to provide the locked_round. We do + however check that all preendorments have the same round in + [check_construction_preendorsement_round_consistency] further below. *) + let* () = check_branch kind cons_info.predecessor_hash branch in + check_payload_hash kind expected_payload_hash block_payload_hash + + let check_preendorsement_content_mempool vi (consensus_info : consensus_info) + branch {level; round; block_payload_hash; _} = + let open Result_syntax in + let kind = Preendorsement in + match Consensus.endorsement_branch vi.ctxt with + | None -> + let expected = consensus_info.predecessor_level in + let provided = level in + error (Consensus_operation_for_future_level {kind; expected; provided}) + | Some (expected_branch, expected_payload_hash) -> + let* () = check_level kind consensus_info.predecessor_level level in + let* () = check_round kind consensus_info.predecessor_round round in + let* () = check_branch kind expected_branch branch in + check_payload_hash kind expected_payload_hash block_payload_hash + let check_preendorsement vi ~check_signature (operation : Kind.preendorsement operation) = let open Lwt_result_syntax in @@ -757,24 +823,31 @@ module Consensus = struct let (Single (Preendorsement consensus_content)) = operation.protocol_data.contents in - let kind = Preendorsement in - let*? expected_features, block_round = - get_expected_preendorsements_features consensus_info consensus_content - in - let*? () = - check_round_not_too_high ~block_round ~provided:consensus_content.round - in let*? () = - check_consensus_features - kind - expected_features - consensus_content - operation + match vi.mode with + | Application block_info | Partial_validation block_info -> + check_preendorsement_content_preexisting_block + vi + block_info + operation.shell.branch + consensus_content + | Construction construction_info -> + check_preendorsement_content_construction + vi + construction_info + operation.shell.branch + consensus_content + | Mempool _ -> + check_preendorsement_content_mempool + vi + consensus_info + operation.shell.branch + consensus_content in let*? consensus_key, voting_power = get_delegate_details consensus_info.preendorsement_slot_map - kind + Preendorsement consensus_content in let* () = @@ -833,7 +906,8 @@ module Consensus = struct | None -> Some (consensus_content.round, voting_power) | Some (_stored_round, evidences) -> (* [_stored_round] is always equal to [consensus_content.round]. - Indeed, this is ensured by {!check_round_equal} in + Indeed, this is ensured by + {!check_preendorsement_content_preexisting_block} in application and partial validation modes, and by {!check_construction_preendorsement_round_consistency} in construction mode. *) @@ -1154,43 +1228,30 @@ module Consensus = struct in {vs with consensus_state = {vs.consensus_state with dal_attestation_seen}} - let check_construction_preendorsement_round_consistency vi block_state kind + (** In Construction mode, check that the preendorsement has the same + round as any previously validated preendorsements. + + This check is not needed in other modes because + {!check_preendorsement} already checks that all preendorsements + have the same expected round (the locked_round in Application and + Partial_validation modes when there is one (otherwise all + preendorsements are rejected so the point is moot), or the + predecessor_round in Mempool mode). *) + let check_construction_preendorsement_round_consistency vi block_state (consensus_content : consensus_content) = let open Result_syntax in - let* consensus_info = - Option.value_e - ~error:(trace_of_error Consensus_operation_not_allowed) - vi.consensus_info - in - let* expected_features, _block_round = - get_expected_preendorsements_features consensus_info consensus_content - in - match expected_features.round with - | Some _ -> - (* When [expected_features.round] has a value (ie. in - application and partial validation modes when the block - fitness has a [locked_round], and always in mempool mode), - [check_preendorsement] already checks that all - preendorsements have this expected round, so checking - anything here would be redundant. Also note that when the - fitness contains no [locked_round], this code is - unreachable because [get_expected_preendorsements_features] - returns an error. *) - return_unit - | None -> ( - (* For preendorsements in block construction mode, - [expected_features.round] has been set to [None] because we - could not know yet whether there is a locked round. *) + match vi.mode with + | Construction _ -> ( match block_state.locked_round_evidence with | None -> - (* This is the first validated preendorsement in - construction mode: there is nothing to check. *) + (* This is the first validated preendorsement: + there is nothing to check. *) return_unit | Some (expected, _power) -> - (* Other preendorsements have already been validated: we - check that the current operation has the same round as - them. *) - check_round kind expected consensus_content) + (* Other preendorsements have already been validated: we check + that the current operation has the same round as them. *) + check_round Preendorsement expected consensus_content.round) + | Application _ | Partial_validation _ | Mempool _ -> return_unit let validate_preendorsement ~check_signature info operation_state block_state oph (operation : Kind.preendorsement operation) = @@ -1203,7 +1264,6 @@ module Consensus = struct check_construction_preendorsement_round_consistency info block_state - Preendorsement consensus_content in let*? () = -- GitLab From 764303796d96c666de850b77b0f037e9f8738f62 Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 22 Feb 2023 16:10:08 +0100 Subject: [PATCH 5/7] Proto/validate: update normal endorsement checks --- src/proto_alpha/lib_protocol/validate.ml | 73 +++++++++++++++--------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index cb71433c1c2f..d486cf1b72b9 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -990,45 +990,62 @@ module Consensus = struct consensus_state = {vs.consensus_state with grandparent_endorsements_seen}; } - let get_expected_endorsements_features consensus_info consensus_content = - match consensus_info.all_expected_features.expected_endorsement with - | Expected_endorsement {expected_features} -> ok expected_features - | No_expected_branch_for_block_endorsement -> - error Unexpected_endorsement_in_block - | No_expected_branch_for_partial_construction_endorsement {expected_level} - -> - error - (Consensus_operation_for_future_level - { - kind = Endorsement; - expected = expected_level; - provided = consensus_content.Alpha_context.level; - }) - | No_predecessor_info_cannot_validate_endorsement -> - error Consensus_operation_not_allowed - type endorsement_kind = Grandparent_endorsement | Normal_endorsement of int + (** Retrieve the expected branch and payload_hash for endorsements + from the context. + + [Consensus.endorsement_branch] only returns [None] when the + predecessor is the protocol activation block, which is always + considered final and should not be endorsed. In that case, return + an error depending on the mode. *) + let expected_branch_and_payload_hash vi (consensus_info : consensus_info) + op_level = + match Consensus.endorsement_branch vi.ctxt with + | Some branch_and_payload_hash -> ok branch_and_payload_hash + | None -> + error + (match vi.mode with + | Application _ | Partial_validation _ | Construction _ -> + (* The block should not contain any endorsements. The + validation of the endorsement fails, and so will the + validation of the whole block. *) + Unexpected_endorsement_in_block + | Mempool _ -> + (* The block that will be built on top on the mempool head + should contain no endorsements, and this is not a + grandparent endorsement (otherwise + [check_normal_endorsement] would not have been called). It + is probably an early endorsement for the next level, hence + the error (and even if this is not the case, hopefully the + levels recorded in the error will provide a hint to what + happened). *) + Consensus_operation_for_future_level + { + kind = Endorsement; + expected = consensus_info.predecessor_level; + provided = op_level; + }) + (** Validate an endorsement pointing to the predecessor, aka a "normal" endorsement. Only this kind of endorsement may be found - during block validation or construction. *) + during block validation or construction (ie. [Application], + [Partial_validation], or [Construction] modes). *) let check_normal_endorsement vi consensus_info ~check_signature (operation : Kind.endorsement operation) = let open Lwt_result_syntax in let (Single (Endorsement consensus_content)) = operation.protocol_data.contents in - let kind = Endorsement in - let*? expected_features = - get_expected_endorsements_features consensus_info consensus_content - in - let*? () = - check_consensus_features - kind - expected_features - consensus_content - operation + let {level; round; block_payload_hash = bph; _} = consensus_content in + let*? expected_branch, expected_payload_hash = + expected_branch_and_payload_hash vi consensus_info level in + let kind = Endorsement in + let*? () = check_level kind consensus_info.predecessor_level level in + let*? () = check_round kind consensus_info.predecessor_round round in + let*? () = check_branch kind expected_branch operation.shell.branch in + let*? () = check_payload_hash kind expected_payload_hash bph in let*? consensus_key, voting_power = get_delegate_details consensus_info.endorsement_slot_map -- GitLab From 56b0af18dbf9295a45b8dbc0f0b231464f72eaeb Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 22 Feb 2023 17:27:13 +0100 Subject: [PATCH 6/7] Proto/validate: update grandparent endorsement checks --- src/proto_alpha/lib_protocol/validate.ml | 78 +++++------------------- 1 file changed, 14 insertions(+), 64 deletions(-) diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index d486cf1b72b9..99a0fdbefd5f 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -667,53 +667,6 @@ module Consensus = struct Tez.(frozen_deposits.current_amount > zero) (Zero_frozen_deposits delegate_pkh) - let check_level_equal kind expected_features - (consensus_content : consensus_content) = - let expected = expected_features.level in - let provided = consensus_content.level in - error_unless - (Raw_level.equal expected provided) - (if Raw_level.(expected > provided) then - Consensus_operation_for_old_level {kind; expected; provided} - else Consensus_operation_for_future_level {kind; expected; provided}) - - let check_round kind expected (consensus_content : consensus_content) = - let provided = consensus_content.round in - error_unless - (Round.equal expected provided) - (if Round.(expected > provided) then - Consensus_operation_for_old_round {kind; expected; provided} - else Consensus_operation_for_future_round {kind; expected; provided}) - - let check_round_equal kind (expected_features : expected_features) - (consensus_content : consensus_content) = - match expected_features.round with - | Some expected -> check_round kind expected consensus_content - | None -> ok_unit - - let check_branch_equal kind expected_features (operation : 'a operation) = - let expected = expected_features.branch in - let provided = operation.shell.branch in - error_unless - (Block_hash.equal expected provided) - (Wrong_consensus_operation_branch {kind; expected; provided}) - - let check_payload_hash_equal kind (expected_features : expected_features) - (consensus_content : consensus_content) = - let expected = expected_features.payload_hash in - let provided = consensus_content.block_payload_hash in - error_unless - (Block_payload_hash.equal expected provided) - (Wrong_payload_hash_for_consensus_operation {kind; expected; provided}) - - let check_consensus_features kind (expected : expected_features) - (consensus_content : consensus_content) (operation : 'a operation) = - let open Result_syntax in - let* () = check_level_equal kind expected consensus_content in - let* () = check_round_equal kind expected consensus_content in - let* () = check_branch_equal kind expected operation in - check_payload_hash_equal kind expected consensus_content - let get_delegate_details slot_map kind consensus_content = Result.of_option (Slot.Map.find consensus_content.slot slot_map) @@ -930,18 +883,19 @@ module Consensus = struct {vs with consensus_state = {vs.consensus_state with preendorsements_seen}} (** Validate an endorsement pointing to the grandparent block. This - function will only be called in [Partial_construction] mode. *) - let check_grandparent_endorsement vi ~check_signature expected operation - (consensus_content : consensus_content) = + function will only be called in [Mempool] mode. *) + let check_grandparent_endorsement vi ~check_signature grandparent + (operation : _ operation) {level; round; block_payload_hash = bph; slot} = let open Lwt_result_syntax in - let kind = Grandparent_endorsement in - let level = Level.from_raw vi.ctxt consensus_content.level in let* (_ctxt : t), consensus_key = - Stake_distribution.slot_owner vi.ctxt level consensus_content.slot - in - let*? () = - check_consensus_features kind expected consensus_content operation + Stake_distribution.slot_owner vi.ctxt (Level.from_raw vi.ctxt level) slot in + let kind = Grandparent_endorsement in + (* This function is only called on endorsements whose level is the + grandparent's, so there is no need to check the level. *) + let*? () = check_round kind grandparent.round round in + let*? () = check_branch kind grandparent.hash operation.shell.branch in + let*? () = check_payload_hash kind grandparent.payload_hash bph in let*? () = if check_signature then Operation.check_signature @@ -1112,19 +1066,15 @@ module Consensus = struct let (Single (Endorsement consensus_content)) = operation.protocol_data.contents in - match - consensus_info.all_expected_features - .expected_grandparent_endorsement_for_partial_construction - with - | Some expected_grandparent_endorsement + match vi.mode with + | Mempool (Some grandparent) when Raw_level.( - consensus_content.level = expected_grandparent_endorsement.level) - -> + succ consensus_content.level = consensus_info.predecessor_level) -> let* () = check_grandparent_endorsement vi ~check_signature - expected_grandparent_endorsement + grandparent operation (consensus_content : consensus_content) in -- GitLab From d6ad4017f2508f6b2df8cd2908bdab272ef40835 Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Thu, 23 Feb 2023 14:59:33 +0100 Subject: [PATCH 7/7] Proto/validate: remove all_expected_consensus_features --- src/proto_alpha/lib_protocol/validate.ml | 252 +---------------------- 1 file changed, 8 insertions(+), 244 deletions(-) diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 99a0fdbefd5f..ec71a224a49a 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -26,87 +26,17 @@ open Validate_errors open Alpha_context -(** Since the expected features of preendorsement and endorsement are - the same for all operations in the considered block, we compute - them once and for all at the begining of the block. - - See [expected_features_for_application], - [expected_features_for_construction], and - [expected_features_for_partial_construction] in the [Consensus] - module below. *) -type expected_features = { - level : Raw_level.t; - round : Round.t option; - (** This always contains a value, except for the case of - preendorsements during block construction. See - [Consensus.check_round_equal] below for its usage. *) - branch : Block_hash.t; - payload_hash : Block_payload_hash.t; -} - -type expected_preendorsement = - | Expected_preendorsement of { - expected_features : expected_features; - block_round : Round.t option; - (** During block validation or construction, we must also check that - the preendorsement round is lower than the block round. In - mempool mode, this field is [None]. *) - } - | No_locked_round_for_block_validation_preendorsement - (** A preexisting block whose fitness indicates no locked round - should contain no preendorsements. *) - | Fresh_proposal_for_construction_preendorsement - (** A constructed block with a fresh proposal should contain no - preendorsements. *) - | No_expected_branch_for_partial_construction_preendorsement of { - expected_level : Raw_level.t; - } - (** See [No_expected_branch_for_partial_construction_endorsement] below. *) - | No_predecessor_info_cannot_validate_preendorsement - (** We do not have access to predecessor level, round, etc. so any - preendorsement validation will fail. *) - -type expected_endorsement = - | Expected_endorsement of {expected_features : expected_features} - | No_expected_branch_for_block_endorsement - (** The context contains no branch: this happens to the first block - that uses the Tenderbake consensus algorithm. This block contains - no endorsements. *) - | No_expected_branch_for_partial_construction_endorsement of { - expected_level : Raw_level.t; - } - (** Same as [No_expected_branch_for_block_endorsement]. This has a - separate constructor because the error raised is distinct: in - mempool mode, we simply assume that we have received a - preendorsement for a future block to which we have not switched - yet. *) - | No_predecessor_info_cannot_validate_endorsement - (** We do not have access to predecessor level, round, etc. so any - endorsement validation will fail. *) - -type all_expected_consensus_features = { - expected_preendorsement : expected_preendorsement; - expected_endorsement : expected_endorsement; - expected_grandparent_endorsement_for_partial_construction : - expected_features option; - (** This only has a value in Mempool mode and when the [ctxt] has a - [grandparent_branch]; it is [None] in all other cases. *) -} - type consensus_info = { predecessor_level : Raw_level.t; predecessor_round : Round.t; - all_expected_features : all_expected_consensus_features; preendorsement_slot_map : (Consensus_key.pk * int) Slot.Map.t; endorsement_slot_map : (Consensus_key.pk * int) Slot.Map.t; } -let init_consensus_info ctxt all_expected_features - (predecessor_level, predecessor_round) = +let init_consensus_info ctxt (predecessor_level, predecessor_round) = { predecessor_level; predecessor_round; - all_expected_features; preendorsement_slot_map = Consensus.allowed_preendorsements ctxt; endorsement_slot_map = Consensus.allowed_endorsements ctxt; } @@ -495,12 +425,9 @@ type validation_state = { let ok_unit = Result_syntax.return_unit -let init_info ctxt mode chain_id ~predecessor_level_and_round - all_expected_consensus_characteristics = +let init_info ctxt mode chain_id ~predecessor_level_and_round = let consensus_info = - Option.map - (init_consensus_info ctxt all_expected_consensus_characteristics) - predecessor_level_and_round + Option.map (init_consensus_info ctxt) predecessor_level_and_round in { ctxt; @@ -541,123 +468,6 @@ let get_initial_ctxt {info; _} = info.ctxt (** Validation of consensus operations (validation pass [0]): preendorsement, endorsement, and dal_attestation. *) module Consensus = struct - let expected_endorsement_features ~predecessor_level ~predecessor_round branch - payload_hash = - { - level = predecessor_level.Level.level; - round = Some predecessor_round; - branch; - payload_hash; - } - - (** Expected endorsement features for all modes in which a block is - considered: application, partial validation, and construction. *) - let expected_endorsement_for_block ctxt ~predecessor_level ~predecessor_round - : expected_endorsement = - match Consensus.endorsement_branch ctxt with - | None -> No_expected_branch_for_block_endorsement - | Some (branch, payload_hash) -> - let expected_features = - expected_endorsement_features - ~predecessor_level - ~predecessor_round - branch - payload_hash - in - Expected_endorsement {expected_features} - - (** Retrieve the expected consensus features for both application and - partial validation modes. *) - let expected_features_for_application ctxt fitness payload_hash - ~predecessor_level ~predecessor_round ~predecessor_hash = - let expected_preendorsement = - match Fitness.locked_round fitness with - | None -> No_locked_round_for_block_validation_preendorsement - | Some locked_round -> - let expected_features = - { - level = (Level.current ctxt).level; - round = Some locked_round; - branch = predecessor_hash; - payload_hash; - } - in - let block_round = Some (Fitness.round fitness) in - Expected_preendorsement {expected_features; block_round} - in - let expected_endorsement = - expected_endorsement_for_block ctxt ~predecessor_level ~predecessor_round - in - { - expected_preendorsement; - expected_endorsement; - expected_grandparent_endorsement_for_partial_construction = None; - } - - let expected_features_for_construction ctxt round payload_hash - ~predecessor_level ~predecessor_round ~predecessor_hash = - let expected_preendorsement = - if Block_payload_hash.(payload_hash = zero) then - (* When the proposal is fresh, a fake [payload_hash] of [zero] - has been provided. In this case, the block should not - contain any preendorsements. *) - Fresh_proposal_for_construction_preendorsement - else - let expected_features = - { - level = (Level.current ctxt).level; - round = None; - branch = predecessor_hash; - payload_hash; - } - in - Expected_preendorsement {expected_features; block_round = Some round} - in - let expected_endorsement = - expected_endorsement_for_block ctxt ~predecessor_level ~predecessor_round - in - { - expected_preendorsement; - expected_endorsement; - expected_grandparent_endorsement_for_partial_construction = None; - } - - let expected_features_for_partial_construction ctxt ~predecessor_level - ~predecessor_round ~grandparent_round = - let expected_preendorsement, expected_endorsement = - match Consensus.endorsement_branch ctxt with - | None -> - let expected_level = predecessor_level.Level.level in - ( No_expected_branch_for_partial_construction_preendorsement - {expected_level}, - No_expected_branch_for_partial_construction_endorsement - {expected_level} ) - | Some (branch, payload_hash) -> - let expected_features = - expected_endorsement_features - ~predecessor_level - ~predecessor_round - branch - payload_hash - in - ( Expected_preendorsement {expected_features; block_round = None}, - Expected_endorsement {expected_features} ) - in - let expected_grandparent_endorsement_for_partial_construction = - match - ( Consensus.grand_parent_branch ctxt, - Raw_level.pred predecessor_level.level ) - with - | None, _ | _, None -> None - | Some (branch, payload_hash), Some level -> - Some {level; round = Some grandparent_round; branch; payload_hash} - in - { - expected_preendorsement; - expected_endorsement; - expected_grandparent_endorsement_for_partial_construction; - } - open Validate_errors.Consensus let check_frozen_deposits_are_positive ctxt delegate_pkh = @@ -2661,16 +2471,8 @@ module Manager = struct return {info; operation_state; block_state} end -let init_validation_state ctxt mode chain_id all_expected_consensus_features - ~predecessor_level_and_round = - let info = - init_info - ctxt - mode - chain_id - ~predecessor_level_and_round - all_expected_consensus_features - in +let init_validation_state ctxt mode chain_id ~predecessor_level_and_round = + let info = init_info ctxt mode chain_id ~predecessor_level_and_round in let predecessor_level = match predecessor_level_and_round with | Some (predecessor_level, _) -> predecessor_level @@ -2723,7 +2525,6 @@ let begin_any_application ctxt chain_id ~predecessor_level current_level ~round:block_header.protocol_data.contents.payload_round in - let payload_hash = block_header.protocol_data.contents.payload_hash in let predecessor_hash = block_header.shell.predecessor in let block_info = { @@ -2738,23 +2539,13 @@ let begin_any_application ctxt chain_id ~predecessor_level let mode = if is_partial then Partial_validation block_info else Application block_info in - let all_expected_consensus_features = - Consensus.expected_features_for_application - ctxt - fitness - payload_hash - ~predecessor_level - ~predecessor_round - ~predecessor_hash - in let validation_state = init_validation_state ctxt mode chain_id - all_expected_consensus_features ~predecessor_level_and_round: - (Some (predecessor_level.level, predecessor_round)) + (Some (predecessor_level.Level.level, predecessor_round)) in return validation_state @@ -2807,15 +2598,6 @@ let begin_full_construction ctxt chain_id ~predecessor_level ~predecessor_round current_level ~round:header_contents.payload_round in - let all_expected_consensus_features = - Consensus.expected_features_for_construction - ctxt - round - header_contents.payload_hash - ~predecessor_level - ~predecessor_round - ~predecessor_hash - in let validation_state = init_validation_state ctxt @@ -2828,21 +2610,13 @@ let begin_full_construction ctxt chain_id ~predecessor_level ~predecessor_round header_contents; }) chain_id - all_expected_consensus_features ~predecessor_level_and_round: - (Some (predecessor_level.level, predecessor_round)) + (Some (predecessor_level.Level.level, predecessor_round)) in return validation_state let begin_partial_construction ctxt chain_id ~predecessor_level ~predecessor_round ~grandparent_round = - let all_expected_consensus_features = - Consensus.expected_features_for_partial_construction - ctxt - ~predecessor_level - ~predecessor_round - ~grandparent_round - in let grandparent = Option.map (fun (hash, payload_hash) -> @@ -2854,26 +2628,16 @@ let begin_partial_construction ctxt chain_id ~predecessor_level ctxt (Mempool grandparent) chain_id - all_expected_consensus_features ~predecessor_level_and_round: - (Some (predecessor_level.level, predecessor_round)) + (Some (predecessor_level.Level.level, predecessor_round)) in validation_state let begin_no_predecessor_info ctxt chain_id = - let all_expected_consensus_features = - { - expected_preendorsement = - No_predecessor_info_cannot_validate_preendorsement; - expected_endorsement = No_predecessor_info_cannot_validate_endorsement; - expected_grandparent_endorsement_for_partial_construction = None; - } - in init_validation_state ctxt (Mempool None) chain_id - all_expected_consensus_features ~predecessor_level_and_round:None let check_operation ?(check_signature = true) info (type kind) -- GitLab