diff --git a/src/proto_015_PtLimaPt/lib_protocol/test/helpers/incremental.ml b/src/proto_015_PtLimaPt/lib_protocol/test/helpers/incremental.ml index e9e10da350af042aeeefdd0de3b9c2a3de4aa3a1..65dbd4073c72803bbc2390ae9f50c821cb188653 100644 --- a/src/proto_015_PtLimaPt/lib_protocol/test/helpers/incremental.ml +++ b/src/proto_015_PtLimaPt/lib_protocol/test/helpers/incremental.ml @@ -194,7 +194,8 @@ let validate_operation ?expect_failure ?check_size st op = | None, Ok validation_state -> return {st with state = (validation_state, application_state)} -let add_operation ?expect_failure ?expect_apply_failure ?check_size st op = +let add_operation ?expect_failure ?expect_apply_failure ?allow_manager_failure + ?check_size st op = let open Lwt_result_syntax in let open Apply_results in let* st = validate_operation ?expect_failure ?check_size st op in @@ -216,19 +217,22 @@ let add_operation ?expect_failure ?expect_apply_failure ?check_size st op = rev_tickets = metadata :: st.rev_tickets; } in - match (expect_apply_failure, metadata) with - | None, No_operation_metadata -> return st - | None, Operation_metadata result -> - let*? () = detect_script_failure result in - return st - | Some _, No_operation_metadata -> - failwith "Error expected while adding operation" - | Some f, Operation_metadata result -> ( - match detect_script_failure result with - | Ok _ -> failwith "Error expected while adding operation" - | Error err -> - let* () = f err in - return st)) + match allow_manager_failure with + | Some true -> return st + | None | Some false -> ( + match (expect_apply_failure, metadata) with + | None, No_operation_metadata -> return st + | None, Operation_metadata result -> + let*? () = detect_script_failure result in + return st + | Some _, No_operation_metadata -> + failwith "Error expected while adding operation" + | Some f, Operation_metadata result -> ( + match detect_script_failure result with + | Ok _ -> failwith "Error expected while adding operation" + | Error err -> + let* () = f err in + return st))) let finalize_validation_and_application (validation_state, application_state) shell_header = diff --git a/src/proto_015_PtLimaPt/lib_protocol/test/helpers/incremental.mli b/src/proto_015_PtLimaPt/lib_protocol/test/helpers/incremental.mli index dc543c0d78e78372b624b2b5f26e1f9aef4fc1c5..83f8f4bb8d9acb581447f444742c0902826e3303 100644 --- a/src/proto_015_PtLimaPt/lib_protocol/test/helpers/incremental.mli +++ b/src/proto_015_PtLimaPt/lib_protocol/test/helpers/incremental.mli @@ -100,12 +100,16 @@ val validate_operation : application of [op] does not fail and [expect_apply_failure] is provided, [add_operation] fails.} + {ul {li [?allow_manager_failure] marks that manager operation + failures after fee taken are ignored.}} + {li [?check_size:bool]: enable the check that an operation size should not exceed [Constants_repr.max_operation_data_length]. Enabled (set to [true]) by default. }} *) val add_operation : ?expect_failure:(error list -> unit tzresult Lwt.t) -> ?expect_apply_failure:(error list -> unit tzresult Lwt.t) -> + ?allow_manager_failure:bool -> ?check_size:bool -> incremental -> Operation.packed -> diff --git a/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/manager_operation_helpers.ml b/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/manager_operation_helpers.ml index 4aa5fad6f7bc411dd073eacfdc0aff182ad04511..e447e5bb1143675e13eec24e7308e130dcc418c4 100644 --- a/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/manager_operation_helpers.ml +++ b/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/manager_operation_helpers.ml @@ -35,6 +35,8 @@ let gb_limit = Gas.Arith.(integral_of_int_exn 100_000) let half_gb_limit = Gas.Arith.(integral_of_int_exn 50_000) +let default_fund = Tez.of_mutez_exn 400_000_000_000L + (** {2 Datatypes} *) (** Context abstraction in a test. *) @@ -150,9 +152,9 @@ let disabled_zkru = {all_enabled with zkru = false} let ctxt_req_default_to_flag flags = { hard_gas_limit_per_block = None; - fund_src = Some Tez.one; + fund_src = Some default_fund; fund_dest = Some Tez.one; - fund_del = Some Tez.one; + fund_del = Some default_fund; reveal_accounts = true; fund_tx = Some Tez.one; fund_sc = Some Tez.one; @@ -1294,24 +1296,26 @@ let witness ctxt source = (b_in, c_in, g_in) (** According to the witness in pre-state and the probes, computes the - expected outputs. In any mode the expected witness: + expected outputs. In any mode, when the source is not deallocated, + the expected witness: - the balance of source should be the one in the pre-state minus the fee of probes, - the counter of source should be the one in the pre-state plus the number of counter in probes. - Concerning the expected available gas in the block: - In - [Application] mode, it cannot be computed, so we do not expect any, - - In [Mempool] mode, it is the remaining gas after removing the gas - of probes gas from an empty block, - In the [Construction] mode, it - is the remaining gas after removing the gas of probes from the - available gas in the pre-state.*) + Concerning the expected available gas in the block: + - In [Application] mode, it cannot be computed, so we do not expect + any, + - In [Mempool] mode, it is the remaining gas after removing the gas + of probes gas from an empty block, + - In the [Construction] mode, it is the remaining gas after removing + the gas of probes from the available gas in the pre-state.*) let expected_witness witness probes ~mode ctxt = let open Lwt_result_syntax in let b_in, c_in, g_in = witness in let*? b_expected = b_in -? probes.fee in let c_expected = Z.add c_in probes.nb_counter in - let+ g_expected = + let* g_expected = match (g_in, mode) with | Some g_in, Construction -> return_some (Gas.Arith.sub g_in (Gas.Arith.fp probes.gas_limit)) @@ -1327,89 +1331,109 @@ let expected_witness witness probes ~mode ctxt = | None, Construction -> failwith "In Construction mode the witness should return a gas level" in - (b_expected, c_expected, g_expected) + return (b_expected, c_expected, g_expected) (** The validity of a test in positve case, observes that validation - of a manager operation implies the fee payment. This observation - differs according to the validation calling [mode] (see type mode - for more details). Given the values of witness in the pre-state, - the probes of the operation probes and the values of witness in the - post-state, if the validation succeeds then we observe in the - post-state: + of a manager operation implies the fee payment. This observation + differs according to the validation calling [mode] (see type mode + for more details) and that the [source] has been [deallocated]. + Given the values of witness in the pre-state, the probes of the + operation probes and the values of witness in the post-state, if + the validation succeeds while deallocating the [source], [source] + must be unallocated in the post-state. - The balance of source decreases by the fee of probes when - [only_validate] marks that only the validate succeeds. + In case of successful validation Without deallocation, then we + observe in the post-state: - The balance of source decreases at least by fee of probes when - [not only_validate] marks that the application has succeeded, + The balance of source decreases at least by fee of probes when the + application has succeeded, Its counter in the pre-state increases by the number of counter of - probes. + probes. - The remaining gas in the pre-state decreases by the gas of probes, - in [Construction] and [Mempool] mode. + The remaining gas in the pre-state decreases at least by the gas + of probes, in [Construction] and [Mempool] mode. In [Mempool] mode, the remaining gas in the pre-state is always - the available gas in an empty block. + the available gas in an empty block. In the [Application] mode, we do not perform any check on the - available gas. *) -let observe ~only_validate ~mode ctxt_pre ctxt_post op = + available gas. *) +let observe ~mode ~deallocated ctxt_pre ctxt_post op = let open Lwt_result_syntax in - let* probes = manager_content_infos op in - let contract = Contract.Implicit probes.source in - let* witness_in = witness ctxt_pre contract in - let* b_out, c_out, g_out = witness ctxt_post contract in - let* b_expected, c_expected, g_expected = - expected_witness witness_in probes ~mode ctxt_post - in - let b_cmp = - Assert.equal - ~loc:__LOC__ - (if only_validate then Tez.( = ) else Tez.( <= )) - (if only_validate then "Balance update (=)" else "Balance update (<=)") - Tez.pp - in - let* _ = b_cmp b_out b_expected in - let _ = - Assert.equal - Z.equal - ~loc:__LOC__ - "Counter incrementation" - Z.pp_print - c_out - c_expected - in - let g_msg = - match mode with - | Application -> "Gas consumption (application)" - | Mempool -> "Gas consumption (mempool)" - | Construction -> "Gas consumption (construction)" + let check_deallocated ctxt contract = + let* actxt = Context.to_alpha_ctxt ctxt in + let*! res = Contract.must_be_allocated actxt contract in + match Environment.wrap_tzresult res with + | Ok () -> + failwith + "%a should have been deallocated@." + Tezos_crypto.Signature.Public_key_hash.pp + (Context.Contract.pkh contract) + | Error + [ + Environment.Ecoproto_error (Contract_storage.Empty_implicit_contract _); + ] -> + return_unit + | Error errs -> + failwith "unexpected error, got %a@." Error_monad.pp_print_trace errs in - match g_expected with - | None -> Assert.is_none ~loc:__LOC__ ~pp:Gas.Arith.pp g_out - | Some g_expected -> - let* g_out = Assert.get_some ~loc:__LOC__ g_out in + let check_still_allocated ctxt_pre ctxt_post probes contract = + let* witness_in = witness ctxt_pre contract in + let* b_out, c_out, g_out = witness ctxt_post contract in + let* b_expected, c_expected, g_expected = + expected_witness witness_in probes ~mode ctxt_post + in + let b_cmp = Assert.equal ~loc:__LOC__ - Gas.Arith.equal - g_msg - Gas.Arith.pp - g_out - g_expected - -let observe_list ~only_validate ~mode ctxt_pre ctxt_post ops = - List.iter - (fun op -> - let _ = observe ~only_validate ~mode ctxt_pre ctxt_post op in - ()) - ops + Tez.( <= ) + "Balance decreases at least by fees" + Tez.pp + in + let* () = b_cmp b_out b_expected in + let* () = + Assert.equal + Z.equal + ~loc:__LOC__ + "Counter incrementation" + Z.pp_print + c_out + c_expected + in + let g_msg = + match mode with + | Application -> "Gas consumption (application)" + | Mempool -> "Gas consumption (mempool)" + | Construction -> "Gas consumption (construction)" + in + match g_expected with + | None -> Assert.is_none ~loc:__LOC__ ~pp:Gas.Arith.pp g_out + | Some g_expected -> + let* g_out = Assert.get_some ~loc:__LOC__ g_out in + Assert.equal + ~loc:__LOC__ + Gas.Arith.( <= ) + g_msg + Gas.Arith.pp + g_out + g_expected + in + let* probes = manager_content_infos op in + let contract = Contract.Implicit probes.source in + if deallocated then check_deallocated ctxt_post contract + else check_still_allocated ctxt_pre ctxt_post probes contract + +let observe_list ~mode ~deallocated ctxt_pre ctxt_post ops = + List.iter_es (fun op -> observe ~mode ~deallocated ctxt_pre ctxt_post op) ops -let validate_operations inc_in ops = +let validate_operations_effects inc_in ops = let open Lwt_result_syntax in List.fold_left_es (fun inc op -> - let* inc_out = Incremental.validate_operation inc op in + let* inc_out = + Incremental.add_operation ~allow_manager_failure:true inc op + in return inc_out) inc_in ops @@ -1421,20 +1445,20 @@ let pre_state_of_mode ~mode infos = let open Lwt_result_syntax in match mode with | Construction | Mempool -> - let+ inc = Incremental.begin_construction infos.ctxt.block in - Context.I inc + let* inc = Incremental.begin_construction infos.ctxt.block in + return (Context.I inc) | Application -> return (Context.B infos.ctxt.block) (** In [Construction] and [Mempool] mode, the post-state is incrementally built upon a pre-state, whereas in the [Application] mode it is obtained by baking. *) -let post_state_of_mode ~mode ctxt ops infos = +let post_state_of_mode ?(_only_validate = false) ~mode ctxt ops infos = let open Lwt_result_syntax in match (mode, ctxt) with | (Construction | Mempool), Context.I inc_pre -> - let* inc_post = validate_operations inc_pre ops in - let+ block = Incremental.finalize_block inc_post in - (Context.I inc_post, {infos with ctxt = {infos.ctxt with block}}) + let* inc_post = validate_operations_effects inc_pre ops in + let* block = Incremental.finalize_block inc_post in + return (Context.I inc_post, {infos with ctxt = {infos.ctxt with block}}) | Application, Context.B b -> let+ block = Block.bake ~baking_mode:Application ~operations:ops b in (Context.B block, {infos with ctxt = {infos.ctxt with block}}) @@ -1446,32 +1470,21 @@ let post_state_of_mode ~mode ctxt ops infos = (** A positive test builds a pre-state from a mode, and a setting context, then it computes a post-state from the mode, the setting context and the operations. Finally, it observes the result - according to the only_validate status for each operation. + according to the [emptying] status for each operation. + + See [observe] for more details on the observational validation. + If the operation validation succeeds but should be deallocated, + then [deallocated ] must be set. - See [observe] for more details on the observational validation. *) -let validate_with_diagnostic ~only_validate ~mode (infos : infos) ops = + Default mode is [Construction]. *) +let validate_diagnostic ?(deallocated = false) ?(mode = Construction) + (infos : infos) ops = let open Lwt_result_syntax in let* ctxt_pre = pre_state_of_mode ~mode infos in let* ctxt_post, infos = post_state_of_mode ~mode ctxt_pre ops infos in - let _ = observe_list ~only_validate ~mode ctxt_pre ctxt_post ops in + let* () = observe_list ~mode ~deallocated ctxt_pre ctxt_post ops in return infos -(** If only the operation validation succeeds; e.g. the rest of the - application failed then [only_validate] must be set for the - observation validation. - - Default mode is [Construction]. See [observe] for more details. *) -let only_validate_diagnostic ?(mode = Construction) (infos : infos) ops = - validate_with_diagnostic ~only_validate:true ~mode infos ops - -(** If the whole operation application succeeds; e.g. the fee - payment and the full application succeed then [not only_validate] - must be set. - - Default mode is [Construction]. *) -let validate_diagnostic ?(mode = Construction) (infos : infos) ops = - validate_with_diagnostic ~only_validate:false ~mode infos ops - let add_operations ~expect_failure inc_in ops = let open Lwt_result_syntax in let* last, ops = @@ -1502,7 +1515,7 @@ let validate_ko_diagnostic ?(mode = Construction) (infos : infos) ops infos.ctxt.block ~mempool_mode:(mempool_mode_of mode) in - let* _ = add_operations ~expect_failure i ops in + let* (_ : Incremental.t) = add_operations ~expect_failure i ops in return_unit | Application -> ( let*! res = diff --git a/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/test_manager_operation_validation.ml b/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/test_manager_operation_validation.ml index 1264dca31933dafdb6b83b80a1d08b3394aa0480..9f8fcf84853b68585e54abc4585155f6512ea631 100644 --- a/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/test_manager_operation_validation.ml +++ b/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/test_manager_operation_validation.ml @@ -293,7 +293,7 @@ let high_fee_diagnostic (infos : infos) op = let test_high_fee infos kind = let open Lwt_result_syntax in - let*? fee = Tez.(one +? one) |> Environment.wrap_tzresult in + let*? fee = Tez.(one +? default_fund) |> Environment.wrap_tzresult in let* op = select_op { @@ -457,7 +457,7 @@ let test_emptying_self_delegate infos kind = } infos in - let* _ = only_validate_diagnostic infos [op] in + let* _ = validate_diagnostic infos [op] in return_unit (** Minimum gas cost to pass the validation: @@ -484,7 +484,7 @@ let test_empty_undelegate infos kind = } infos in - let* _ = only_validate_diagnostic infos [op] in + let* _ = validate_diagnostic ~deallocated:true infos [op] in return_unit (** No gas consumer with the minimal gas limit for manager operations diff --git a/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/test_validation_batch.ml b/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/test_validation_batch.ml index c823264c6089389b990cc04e4a88b4fec917aa8f..205863081e7960ab1b3ad68f7ced93b3d361a13a 100644 --- a/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/test_validation_batch.ml +++ b/src/proto_015_PtLimaPt/lib_protocol/test/integration/validate/test_validation_batch.ml @@ -417,8 +417,8 @@ let batch_empty_at_end infos kind1 kind2 = (Context.B infos.ctxt.block) [reveal; op_case2; op2_case2] in - let* _ = validate_diagnostic infos [case2] in - let* _ = validate_diagnostic infos [case3] in + let* _ = validate_diagnostic ~deallocated:true infos [case2] in + let* _ = validate_diagnostic ~deallocated:true infos [case3] in return_unit (** Simple reveal followed by a transaction. *) diff --git a/src/proto_alpha/lib_protocol/test/helpers/incremental.ml b/src/proto_alpha/lib_protocol/test/helpers/incremental.ml index 3baf20c3a523316409df9efe98dcfaa635127610..1cf523719e416fd625e8d2a4683749e39329d7ca 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/incremental.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/incremental.ml @@ -194,7 +194,8 @@ let validate_operation ?expect_failure ?check_size st op = | None, Ok validation_state -> return {st with state = (validation_state, application_state)} -let add_operation ?expect_failure ?expect_apply_failure ?check_size st op = +let add_operation ?expect_failure ?expect_apply_failure ?allow_manager_failure + ?check_size st op = let open Lwt_result_syntax in let open Apply_results in let* st = validate_operation ?expect_failure ?check_size st op in @@ -216,19 +217,22 @@ let add_operation ?expect_failure ?expect_apply_failure ?check_size st op = rev_tickets = metadata :: st.rev_tickets; } in - match (expect_apply_failure, metadata) with - | None, No_operation_metadata -> return st - | None, Operation_metadata result -> - let*? () = detect_script_failure result in - return st - | Some _, No_operation_metadata -> - failwith "Error expected while adding operation" - | Some f, Operation_metadata result -> ( - match detect_script_failure result with - | Ok _ -> failwith "Error expected while adding operation" - | Error err -> - let* () = f err in - return st)) + match allow_manager_failure with + | Some true -> return st + | None | Some false -> ( + match (expect_apply_failure, metadata) with + | None, No_operation_metadata -> return st + | None, Operation_metadata result -> + let*? () = detect_script_failure result in + return st + | Some _, No_operation_metadata -> + failwith "Error expected while adding operation" + | Some f, Operation_metadata result -> ( + match detect_script_failure result with + | Ok _ -> failwith "Error expected while adding operation" + | Error err -> + let* () = f err in + return st))) let finalize_validation_and_application (validation_state, application_state) shell_header = diff --git a/src/proto_alpha/lib_protocol/test/helpers/incremental.mli b/src/proto_alpha/lib_protocol/test/helpers/incremental.mli index dc543c0d78e78372b624b2b5f26e1f9aef4fc1c5..1be5fc3dff6bb18c10c5f651c5ae81ced7ec6139 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/incremental.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/incremental.mli @@ -80,32 +80,36 @@ val validate_operation : Operation.packed -> incremental tzresult Lwt.t -(** [add_operation ?expect_failure ?expect_apply_failure ?check_size i - op] tries to validate then apply [op] in the validation and - application state of [i]. If the validation of [op] succeeds, the - function returns the incremental value with a validation state - updated after the application of [op]. Otherwise raise the error - from the validation of [op]. +(** [add_operation ?expect_failure ?expect_apply_failure + ?allow_manager_failure ?check_size i op] tries to validate then + apply [op] in the validation and application state of [i]. If the + validation of [op] succeeds, the function returns the incremental + value with a validation state updated after the application of + [op]. Otherwise raise the error from the validation of [op]. Optional arguments allow to override defaults: {ul {li [?expect_failure:(error list -> unit tzresult Lwt.t)]: validation of [op] is expected to fail and [expect_failure] should handle the error. In case validate does not fail and - [expect_failure] is provided, [validate_operation] fails.} + [expect_failure] is provided, [validate_operation] fails.}} {ul {li [?expect_apply_failure:(error list -> unit tzresult Lwt.t)]: application of [op] is expected to fail and - [expect_apply_failure] should handle the error. In case the + [expect_apply_failure] should handle the errror. In case the application of [op] does not fail and [expect_apply_failure] is - provided, [add_operation] fails.} + provided, [add_operation] fails.}} + + {ul {li [?allow_manager_failure] marks that manager operation + failures after fee taken are ignored.}} {li [?check_size:bool]: enable the check that an operation size should not exceed [Constants_repr.max_operation_data_length]. - Enabled (set to [true]) by default. }} *) + Enabled (set to [true]) by default. } *) val add_operation : ?expect_failure:(error list -> unit tzresult Lwt.t) -> ?expect_apply_failure:(error list -> unit tzresult Lwt.t) -> + ?allow_manager_failure:bool -> ?check_size:bool -> incremental -> Operation.packed -> diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/generators.ml b/src/proto_alpha/lib_protocol/test/integration/validate/generators.ml index 30967c0027ffb6ca5d934c05f32fd6d2a07575d3..5affaba44799e377903d91a3dc5f1e52600b15c9 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/generators.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/generators.ml @@ -278,6 +278,4 @@ let wrap ~name ?print ?(count = 1) ?check ~(gen : 'a QCheck2.Gen.t) ~gen f -let wrap_mode ?(only_validate = false) infos op mode = - if only_validate then only_validate_diagnostic ~mode infos op - else validate_diagnostic ~mode infos op +let wrap_mode infos op mode = validate_diagnostic ~mode infos op diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml b/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml index 724aefb6c9608755004006d3a672d5ad7e5a6df8..e5e16582a0cddfcb07e1dc95e8a9332d99a6f2c3 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml @@ -35,6 +35,8 @@ let gb_limit = Gas.Arith.(integral_of_int_exn 100_000) let half_gb_limit = Gas.Arith.(integral_of_int_exn 50_000) +let default_fund = Tez.of_mutez_exn 400_000_000_000L + (** {2 Datatypes} *) (** Context abstraction in a test. *) @@ -152,9 +154,9 @@ let disabled_zkru = {all_enabled with zkru = false} let ctxt_req_default_to_flag flags = { hard_gas_limit_per_block = None; - fund_src = Some Tez.one; + fund_src = Some default_fund; fund_dest = Some Tez.one; - fund_del = Some Tez.one; + fund_del = Some default_fund; reveal_accounts = true; fund_tx = Some Tez.one; fund_sc = Some Tez.one; @@ -346,8 +348,8 @@ let delegation block source delegate = let* block = Block.bake block ~operation in let* del_opt_new = Context.Contract.delegate_opt (B block) contract_source in let* del = Assert.get_some ~loc:__LOC__ del_opt_new in - let+ () = Assert.equal_pkh ~loc:__LOC__ del delegate_pkh in - block + let* () = Assert.equal_pkh ~loc:__LOC__ del delegate_pkh in + return block let originate_tx_rollup block rollup_account = let open Lwt_result_syntax in @@ -506,14 +508,14 @@ let init_infos : | Some _ -> let account = Account.new_account () in let* block = fund_account block bootstrap account.pkh fund in - let+ block, rollup = + let* block, rollup = match originate_rollup with | None -> return (block, None) | Some f -> let+ block, rollup = f block account in (block, Some rollup) in - (block, Some account, rollup) + return (block, Some account, rollup) in let reveal_accounts_operations b l = List.filter_map_es @@ -1300,7 +1302,7 @@ let rec contents_infos : let*? fee = manop.fee +? probes.fee in let gas_limit = Gas.Arith.add probes.gas_limit manop.gas_limit in let nb_counter = succ probes.nb_counter in - let _ = Assert.equal_pkh ~loc:__LOC__ manop.source probes.source in + let* () = Assert.equal_pkh ~loc:__LOC__ manop.source probes.source in return {fee; source = probes.source; gas_limit; nb_counter} (** Computes a [probes] from a list of manager contents. *) @@ -1324,23 +1326,25 @@ let available_gas = function let witness ctxt source = let open Lwt_result_syntax in let* b_in = Context.Contract.balance ctxt source in - let+ c_in = Context.Contract.counter ctxt source in + let* c_in = Context.Contract.counter ctxt source in let g_in = available_gas ctxt in - (b_in, c_in, g_in) + return (b_in, c_in, g_in) (** According to the witness in pre-state and the probes, computes the - expected outputs. In any mode the expected witness: + expected outputs. In any mode, when the source is not deallocated, + the expected witness: - the balance of source should be the one in the pre-state minus the fee of probes, - the counter of source should be the one in the pre-state plus the number of counter in probes. - Concerning the expected available gas in the block: - In - [Application] mode, it cannot be computed, so we do not expect any, - - In [Mempool] mode, it is the remaining gas after removing the gas - of probes gas from an empty block, - In the [Construction] mode, it - is the remaining gas after removing the gas of probes from the - available gas in the pre-state.*) + Concerning the expected available gas in the block: + - In [Application] mode, it cannot be computed, so we do not expect + any, + - In [Mempool] mode, it is the remaining gas after removing the gas + of probes gas from an empty block, + - In the [Construction] mode, it is the remaining gas after removing + the gas of probes from the available gas in the pre-state.*) let expected_witness witness probes ~mode ctxt = let open Lwt_result_syntax in let b_in, c_in, g_in = witness in @@ -1348,7 +1352,7 @@ let expected_witness witness probes ~mode ctxt = let c_expected = Manager_counter.Internal_for_tests.add c_in probes.nb_counter in - let+ g_expected = + let* g_expected = match (g_in, mode) with | Some g_in, Construction -> return_some (Gas.Arith.sub g_in (Gas.Arith.fp probes.gas_limit)) @@ -1364,89 +1368,109 @@ let expected_witness witness probes ~mode ctxt = | None, Construction -> failwith "In Construction mode the witness should return a gas level" in - (b_expected, c_expected, g_expected) + return (b_expected, c_expected, g_expected) (** The validity of a test in positve case, observes that validation - of a manager operation implies the fee payment. This observation - differs according to the validation calling [mode] (see type mode - for more details). Given the values of witness in the pre-state, - the probes of the operation probes and the values of witness in the - post-state, if the validation succeeds then we observe in the - post-state: + of a manager operation implies the fee payment. This observation + differs according to the validation calling [mode] (see type mode + for more details) and that the [source] has been [deallocated]. + Given the values of witness in the pre-state, the probes of the + operation probes and the values of witness in the post-state, if + the validation succeeds while deallocating the [source], [source] + must be unallocated in the post-state. - The balance of source decreases by the fee of probes when - [only_validate] marks that only the validate succeeds. + In case of successful validation Without deallocation, then we + observe in the post-state: - The balance of source decreases at least by fee of probes when - [not only_validate] marks that the application has succeeded, + The balance of source decreases at least by fee of probes when the + application has succeeded, Its counter in the pre-state increases by the number of counter of - probes. + probes. - The remaining gas in the pre-state decreases by the gas of probes, - in [Construction] and [Mempool] mode. + The remaining gas in the pre-state decreases at least by the gas + of probes, in [Construction] and [Mempool] mode. In [Mempool] mode, the remaining gas in the pre-state is always - the available gas in an empty block. + the available gas in an empty block. In the [Application] mode, we do not perform any check on the - available gas. *) -let observe ~only_validate ~mode ctxt_pre ctxt_post op = + available gas. *) +let observe ~mode ~deallocated ctxt_pre ctxt_post op = let open Lwt_result_syntax in - let* probes = manager_content_infos op in - let contract = Contract.Implicit probes.source in - let* witness_in = witness ctxt_pre contract in - let* b_out, c_out, g_out = witness ctxt_post contract in - let* b_expected, c_expected, g_expected = - expected_witness witness_in probes ~mode ctxt_post - in - let b_cmp = - Assert.equal - ~loc:__LOC__ - (if only_validate then Tez.( = ) else Tez.( <= )) - (if only_validate then "Balance update (=)" else "Balance update (<=)") - Tez.pp - in - let* () = b_cmp b_out b_expected in - let _ = - Assert.equal - Manager_counter.equal - ~loc:__LOC__ - "Counter incrementation" - Manager_counter.pp - c_out - c_expected - in - let g_msg = - match mode with - | Application -> "Gas consumption (application)" - | Mempool -> "Gas consumption (mempool)" - | Construction -> "Gas consumption (construction)" + let check_deallocated ctxt contract = + let* actxt = Context.to_alpha_ctxt ctxt in + let*! res = Contract.must_be_allocated actxt contract in + match Environment.wrap_tzresult res with + | Ok () -> + failwith + "%a should have been deallocated@." + Tezos_crypto.Signature.Public_key_hash.pp + (Context.Contract.pkh contract) + | Error + [ + Environment.Ecoproto_error (Contract_storage.Empty_implicit_contract _); + ] -> + return_unit + | Error errs -> + failwith "unexpected error, got %a@." Error_monad.pp_print_trace errs in - match g_expected with - | None -> Assert.is_none ~loc:__LOC__ ~pp:Gas.Arith.pp g_out - | Some g_expected -> - let* g_out = Assert.get_some ~loc:__LOC__ g_out in + let check_still_allocated ctxt_pre ctxt_post probes contract = + let* witness_in = witness ctxt_pre contract in + let* b_out, c_out, g_out = witness ctxt_post contract in + let* b_expected, c_expected, g_expected = + expected_witness witness_in probes ~mode ctxt_post + in + let b_cmp = Assert.equal ~loc:__LOC__ - Gas.Arith.equal - g_msg - Gas.Arith.pp - g_out - g_expected - -let observe_list ~only_validate ~mode ctxt_pre ctxt_post ops = - List.iter - (fun op -> - let _ = observe ~only_validate ~mode ctxt_pre ctxt_post op in - ()) - ops + Tez.( <= ) + "Balance decreases at least by fees" + Tez.pp + in + let* () = b_cmp b_out b_expected in + let* () = + Assert.equal + Manager_counter.equal + ~loc:__LOC__ + "Counter incrementation" + Manager_counter.pp + c_out + c_expected + in + let g_msg = + match mode with + | Application -> "Gas consumption (application)" + | Mempool -> "Gas consumption (mempool)" + | Construction -> "Gas consumption (construction)" + in + match g_expected with + | None -> Assert.is_none ~loc:__LOC__ ~pp:Gas.Arith.pp g_out + | Some g_expected -> + let* g_out = Assert.get_some ~loc:__LOC__ g_out in + Assert.equal + ~loc:__LOC__ + Gas.Arith.( <= ) + g_msg + Gas.Arith.pp + g_out + g_expected + in + let* probes = manager_content_infos op in + let contract = Contract.Implicit probes.source in + if deallocated then check_deallocated ctxt_post contract + else check_still_allocated ctxt_pre ctxt_post probes contract + +let observe_list ~mode ~deallocated ctxt_pre ctxt_post ops = + List.iter_es (fun op -> observe ~mode ~deallocated ctxt_pre ctxt_post op) ops -let validate_operations inc_in ops = +let validate_operations_effects inc_in ops = let open Lwt_result_syntax in List.fold_left_es (fun inc op -> - let* inc_out = Incremental.validate_operation inc op in + let* inc_out = + Incremental.add_operation ~allow_manager_failure:true inc op + in return inc_out) inc_in ops @@ -1458,24 +1482,24 @@ let pre_state_of_mode ~mode infos = let open Lwt_result_syntax in match mode with | Construction | Mempool -> - let+ inc = Incremental.begin_construction infos.ctxt.block in - Context.I inc + let* inc = Incremental.begin_construction infos.ctxt.block in + return (Context.I inc) | Application -> return (Context.B infos.ctxt.block) (** In [Construction] and [Mempool] mode, the post-state is incrementally built upon a pre-state, whereas in the [Application] mode it is obtained by baking. *) -let post_state_of_mode ?(only_validate = false) ~mode ctxt ops infos = +let post_state_of_mode ?(_only_validate = false) ~mode ctxt ops infos = let open Lwt_result_syntax in match (mode, ctxt) with | (Construction | Mempool), Context.I inc_pre -> - let* inc_post = validate_operations inc_pre ops in - let+ block = Incremental.finalize_block inc_post in - (Context.I inc_post, {infos with ctxt = {infos.ctxt with block}}) + let* inc_post = validate_operations_effects inc_pre ops in + let* block = Incremental.finalize_block inc_post in + return (Context.I inc_post, {infos with ctxt = {infos.ctxt with block}}) | Application, Context.B b -> let+ block = Block.bake - ~allow_manager_failures:only_validate + ~allow_manager_failures:true ~baking_mode:Application ~operations:ops b @@ -1489,34 +1513,21 @@ let post_state_of_mode ?(only_validate = false) ~mode ctxt ops infos = (** A positive test builds a pre-state from a mode, and a setting context, then it computes a post-state from the mode, the setting context and the operations. Finally, it observes the result - according to the only_validate status for each operation. + according to the [emptying] status for each operation. + + See [observe] for more details on the observational validation. + If the operation validation succeeds but should be deallocated, + then [deallocated ] must be set. - See [observe] for more details on the observational validation. *) -let validate_with_diagnostic ~only_validate ~mode (infos : infos) ops = + Default mode is [Construction]. *) +let validate_diagnostic ?(deallocated = false) ?(mode = Construction) + (infos : infos) ops = let open Lwt_result_syntax in let* ctxt_pre = pre_state_of_mode ~mode infos in - let* ctxt_post, infos = - post_state_of_mode ~only_validate ~mode ctxt_pre ops infos - in - let _ = observe_list ~only_validate ~mode ctxt_pre ctxt_post ops in + let* ctxt_post, infos = post_state_of_mode ~mode ctxt_pre ops infos in + let* () = observe_list ~mode ~deallocated ctxt_pre ctxt_post ops in return infos -(** If only the operation validation succeeds; e.g. the rest of the - application failed then [only_validate] must be set for the - observation validation. - - Default mode is [Construction]. See [observe] for more details. *) -let only_validate_diagnostic ?(mode = Construction) (infos : infos) ops = - validate_with_diagnostic ~only_validate:true ~mode infos ops - -(** If the whole operation application succeeds; e.g. the fee - payment and the full application succeed then [not only_validate] - must be set. - - Default mode is [Construction]. *) -let validate_diagnostic ?(mode = Construction) (infos : infos) ops = - validate_with_diagnostic ~only_validate:false ~mode infos ops - let add_operations ~expect_failure inc_in ops = let open Lwt_result_syntax in let* last, ops = diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/test_1m_restriction.ml b/src/proto_alpha/lib_protocol/test/integration/validate/test_1m_restriction.ml index 2e5ef078bcc4ec7fd69ebb48f7c49acf05e71fda..f4a2fbb75a99ac591cc84e02c09c239ab29d9130 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/test_1m_restriction.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/test_1m_restriction.ml @@ -44,7 +44,7 @@ let ctxt_cstrs_default = default_ctxt_cstrs with src_cstrs = Pure 1500000; dest_cstrs = Pure 15000; - del_cstrs = Pure 15000; + del_cstrs = Pure 150000; tx_cstrs = Pure 15000; sc_cstrs = Pure 15000; zk_cstrs = Pure 15000; @@ -108,7 +108,7 @@ let positive_tests = let open Lwt_result_syntax in let* infos = init_ctxt ctxt_req in let* op = select_op operation_req infos in - let* (_infos : infos) = wrap_mode ~only_validate:true infos [op] mode in + let* (_ : infos) = wrap_mode infos [op] mode in return_true) (** Under 1M restriction, neither a block nor a prevalidator's valid @@ -175,7 +175,7 @@ let batch_is_not_singles_tests = let* batch = Op.batch_operations ~source (B infos.ctxt.block) [op1; op2] in - let* (_ : infos) = only_validate_diagnostic ~mode infos [batch] in + let* (_ : infos) = validate_diagnostic ~mode infos [batch] in let* () = validate_ko_diagnostic ~mode infos [op1; op2] expect_failure in return_true) @@ -213,8 +213,8 @@ let conflict_free_tests = } in let* op2 = select_op operation_req' infos2 in - let* (_ : infos) = only_validate_diagnostic ~mode infos [op1; op2] in - let* (_ : infos) = only_validate_diagnostic ~mode infos [op2; op1] in + let* (_ : infos) = validate_diagnostic ~mode infos [op1; op2] in + let* (_ : infos) = validate_diagnostic ~mode infos [op2; op1] in return_true) open Lib_test.Qcheck2_helpers diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/test_covalidity.ml b/src/proto_alpha/lib_protocol/test/integration/validate/test_covalidity.ml index c2fb1e2a55b936ffe26e35579eb652f933e8ea8e..046d4cf44a9568160b4c5653276251d6913f4c37 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/test_covalidity.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/test_covalidity.ml @@ -112,7 +112,7 @@ let covalid_permutation_and_bake ks nb_bootstrap = |> List.rev_filter is_not_preendorsement in (* Ensure that we can validate and apply this permutation *) - let* (_b : Block.t) = + let* (_ : Block.t) = Block.bake ~allow_manager_failures:true state.block ~operations in loop (pred n) diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/test_manager_operation_validation.ml b/src/proto_alpha/lib_protocol/test/integration/validate/test_manager_operation_validation.ml index e0ab92846cc9716979b7a02b006c15be10aa001e..5d7cbd291e3aa4330ef75aa7b32983c6acf382ea 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/test_manager_operation_validation.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/test_manager_operation_validation.ml @@ -294,7 +294,7 @@ let high_fee_diagnostic (infos : infos) op = let test_high_fee infos kind = let open Lwt_result_syntax in - let*? fee = Tez.(one +? one) |> Environment.wrap_tzresult in + let*? fee = Tez.(one +? default_fund) |> Environment.wrap_tzresult in let* op = select_op { @@ -412,29 +412,23 @@ let test_exceeding_block_gas ~mode infos kind = Notice that in the first two cases only validate succeeds while in the last case, the full application also succeeds. - In the first 2 case, we observe in the output context that: - - the counter is the successor of the one stored in the initial context, - - the balance decreased by fee, - - the available gas in the block decreased by gas limit. - In the last case, we observe in the output context that: + In the case of emptying the balance of an undelegated implicit source, + we observe in the output context that the source is deallocated. + + Otherwise, we observe in the output context that: - the counter is the successor of the one stored in the initial context, - the balance is at least decreased by fee, - - the available gas in the block decreased by gas limit. *) + - the available gas in the block decreased at least gas limit. *) (** Fee payment*) let test_validate infos kind = let open Lwt_result_syntax in - let* counter = - Context.Contract.counter - (B infos.ctxt.block) - (contract_of (get_source infos)) - in let* op = select_op { (operation_req_default kind) with force_reveal = Some true; - counter = Some counter; + amount = Some Tez.one; } infos in @@ -458,7 +452,7 @@ let test_emptying_self_delegate infos kind = } infos in - let* (_ : infos) = only_validate_diagnostic infos [op] in + let* (_ : infos) = validate_diagnostic infos [op] in return_unit (** Minimum gas cost to pass the validation: @@ -485,7 +479,7 @@ let test_empty_undelegate infos kind = } infos in - let* (_ : infos) = only_validate_diagnostic infos [op] in + let* (_ : infos) = validate_diagnostic ~deallocated:true infos [op] in return_unit (** No gas consumer with the minimal gas limit for manager operations diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/test_mempool.ml b/src/proto_alpha/lib_protocol/test/integration/validate/test_mempool.ml index 93b6f2aed1ede8d9c0422b8d57f239290990ade5..4547bed9fa28094a416fe8edb48d2a449f2c62bb 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/test_mempool.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/test_mempool.ml @@ -137,7 +137,7 @@ let test_imcompatible_mempool () = = extract_values ctxt block in - let _vs, mempool1 = + let (_vs : Mempool.validation_info), mempool1 = Mempool.init ctxt Tezos_crypto.Chain_id.zero @@ -153,7 +153,7 @@ let test_imcompatible_mempool () = = extract_values ctxt2 block2 in - let _vs, mempool2 = + let (_vs : Mempool.validation_info), mempool2 = Mempool.init ctxt2 Tezos_crypto.Chain_id.zero diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/test_validation_batch.ml b/src/proto_alpha/lib_protocol/test/integration/validate/test_validation_batch.ml index ba364f0dc2f406015e5008bfd7e87b63ace740e8..6632e3a421b7c2c12690e83fb81d355ff6359ba6 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/test_validation_batch.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/test_validation_batch.ml @@ -429,8 +429,8 @@ let batch_empty_at_end infos kind1 kind2 = (Context.B infos.ctxt.block) [reveal; op_case2; op2_case2] in - let* (_ : infos) = validate_diagnostic infos [case2] in - let* (_ : infos) = validate_diagnostic infos [case3] in + let* (_ : infos) = validate_diagnostic ~deallocated:true infos [case2] in + let* (_ : infos) = validate_diagnostic ~deallocated:true infos [case3] in return_unit (** Simple reveal followed by a transaction. *) @@ -466,7 +466,7 @@ let batch_reveal_transaction infos = (Context.B infos.ctxt.block) [reveal; transaction] in - let* (_i : Incremental.t) = Incremental.begin_construction infos.ctxt.block in + let* (_ : Incremental.t) = Incremental.begin_construction infos.ctxt.block in let* (_ : infos) = validate_diagnostic infos [batch] in return_unit